Allocate an array of integers proportionally compensating for rounding errors

后端 未结 5 697
暖寄归人
暖寄归人 2021-02-04 12:29

I have an array of non-negative values. I want to build an array of values who\'s sum is 20 so that they are proportional to the first array.

This would be an easy probl

5条回答
  •  别跟我提以往
    2021-02-04 13:08

    There's a very simple answer to this question: I've done it many times. After each assignment into the new array, you reduce the values you're working with as follows:

    1. Call the first array A, and the new, proportional array B (which starts out empty).
    2. Call the sum of A elements T
    3. Call the desired sum S.
    4. For each element of the array (i) do the following:
      a. B[i] = round(A[i] / T * S). (rounding to nearest integer, penny or whatever is required)
      b. T = T - A[i]
      c. S = S - B[i]

    That's it! Easy to implement in any programming language or in a spreadsheet.

    The solution is optimal in that the resulting array's elements will never be more than 1 away from their ideal, non-rounded values. Let's demonstrate with your example:
    T = 36, S = 20. B[1] = round(A[1] / T * S) = 2. (ideally, 1.666....)
    T = 33, S = 18. B[2] = round(A[2] / T * S) = 2. (ideally, 1.666....)
    T = 30, S = 16. B[3] = round(A[3] / T * S) = 2. (ideally, 1.666....)
    T = 27, S = 14. B[4] = round(A[4] / T * S) = 2. (ideally, 1.666....)
    T = 24, S = 12. B[5] = round(A[5] / T * S) = 2. (ideally, 1.666....)
    T = 21, S = 10. B[6] = round(A[6] / T * S) = 1. (ideally, 1.666....)
    T = 18, S = 9.   B[7] = round(A[7] / T * S) = 9. (ideally, 10)

    Notice that comparing every value in B with it's ideal value in parentheses, the difference is never more than 1.

    It's also interesting to note that rearranging the elements in the array can result in different corresponding values in the resulting array. I've found that arranging the elements in ascending order is best, because it results in the smallest average percentage difference between actual and ideal.

提交回复
热议问题