I have a vector of fractions a = [0.04352034965262487, 0.480655360084497, 0.02655889003246612, 0.449265400230412, 0.0]
of type float64
such that of course sum(a)=1
. These fractions represent persentages of some number K=128
. So, multiplying a
by K
we obtain the number of elements in each fraction a*K =[5.570604755535983, 61.523886090815616, 3.3995379241556636, 57.50597122949274, 0.0]
.
I want to transform this vector a*K
into an int
vector and respect the sum of elements of a*K
to be K
. What I am doing is floor
but this will give 126
and not 128
. When I do round
I obtain 129
and when I do ceil
I obtain 130
.
I thought of applying ceil
and then remove randomly the 2 elements that exceeds 128
. Is there a better way?
This can be accomplished by first applying floor to a*K
then pick n
items that had the largest fractional parts and add one to them, where n
is K - sum(floor(a*K))
In Python:
from math import floor
aK = [5.570604755535983, 61.523886090815616, 3.3995379241556636, 57.50597122949274, 0.0]
K = 128
# Sum of floored is less than K.
floored = [floor(x) for x in aK]
print(floored, sum(floored))
# Add 1 to each items with largest fractional part
frac = [x - y for x, y in zip(aK,floored)]
frac_rank = sorted(range(len(frac)), key=frac.__getitem__, reverse=True)
for i in frac_rank[:K - sum(floored)]:
floored[i] += 1
# Now floored adds up to K
print(floored, sum(floored))