Allocate an array of integers proportionally compensating for rounding errors

后端 未结 5 700
暖寄归人
暖寄归人 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条回答
  •  -上瘾入骨i
    2021-02-04 13:18

    So the answers and comments above were helpful... particularly the decreasing sum comment from @Frederik.

    The solution I came up with takes advantage of the fact that for an input array v, sum(v_i * 20) is divisible by sum(v). So for each value in v, I mulitply by 20 and divide by the sum. I keep the quotient, and accumulate the remainder. Whenever the accumulator is greater than sum(v), I add one to the value. That way I'm guaranteed that all the remainders get rolled into the results.

    Is that legible? Here's the implementation in Python:

    def proportion(values, total):
        # set up by getting the sum of the values and starting
        # with an empty result list and accumulator
        sum_values = sum(values)
        new_values = []
        acc = 0
    
        for v in values:
            # for each value, find quotient and remainder
            q, r = divmod(v * total, sum_values)
    
            if acc + r < sum_values:
                # if the accumlator plus remainder is too small, just add and move on
                acc += r
            else:
                # we've accumulated enough to go over sum(values), so add 1 to result
                if acc > r:
                    # add to previous
                    new_values[-1] += 1
                else:
                    # add to current
                    q += 1
                acc -= sum_values - r
    
            # save the new value
            new_values.append(q)
    
        # accumulator is guaranteed to be zero at the end
        print new_values, sum_values, acc
    
        return new_values
    

    (I added an enhancement that if the accumulator > remainder, I increment the previous value instead of the current value)

提交回复
热议问题