Rounding Floats While Maintaining Total Sum Equal
Solution 1:
I recently had to solve a similar problem and decided it was something common enough to various projects of mine to generalize a python solution and package it. Check out iteround
.
Solution 2:
Ok, this is going to be a bit mathematical:
You have a series of real numbers Xi Their sum equals N sum(Xi) = N
Let's break each real number to its floor integer and residual real part (between 0 and 1): Xi = Ri + fi
Now, you need a series of integers Yi that are as close to Xi, but are integers and also sum to N. We can break them like this: Yi = Ri + Fi (where Fi is an integer either 0 or 1).
Now we need that: sum(Yi) = sum(Xi) = N
If you break that, you'll get this equation as a requirement for the solution: sum(Fi) = sum(fi) = N - sum(Ri)
Let's denote: K = N - sum(Ri)
Now the solution is simple, choose the K elements which have the largest fi values, and assign their corresponding Fi to 1; assign the other Fi to 0.
Now you have your values for Yi which in your case are the loop sizes
Here's the code for it:
defround_series_retain_integer_sum(xs):
N = sum(xs)
Rs = [round(x) for x in xs]
K = N - sum(Rs)
assert K == round(K)
fs = [x - round(x) for x in xs]
indices = [i for order, (e, i) inenumerate(reversed(sorted((e,i) for i,e inenumerate(fs)))) if order < K]
ys = [R + 1if i in indices else R for i,R inenumerate(Rs)]
return ys
xs = [5.2, 3.4, 2.1, 7.3, 3.25, 6.25, 8.2, 9.1, 10.1, 55.1]
ys = round_series_retain_integer_sum(xs)
print xs, sum(xs)
print ys, sum(ys)
I think I don't have any bugs, I hope you get the idea even if so
Post a Comment for "Rounding Floats While Maintaining Total Sum Equal"