I know how to round a number in Python, this is not a simple technical issue.
My issue is that rounding will make a set of percentages not adding up to 100%, when, technically, they should.
For example:
a = 1
b = 14
I want to compute the percentage of a in (a + b) and b in (a + b).
The answer should be
a/(a + b) = 1/15
b/(a + b) = 14/15
When I try to round those numbers, I got
1/15 = 6.66
14/15 = 93.33
(I was doing the flooring), which makes those two number doesn't add up to 100%.
In this case, we should do ceiling for 1/15, which is 6.67, and flooring for 14/15, which is 93.33. And now they add up to 100%. The rule in this case should be "rounding to the nearest number"
However, if we have a more complicate case, say 3 numbers:
a = 1
b = 7
c = 7
flooring:
1/15 = 6.66
7/15 = 46.66
7/15 = 46.66
Doesn't add up to 100%.
ceiling:
1/15 = 6.67
7/15 = 46.67
7/15 = 46.67
doesn't add up to 100%.
Rounding (to nearest number) is same as ceiling. Still doesn't add up to 100%.
So my question is what should I do to make sure they all add up to 100% in any cases.
Thanks in advance.
UPDATE: Thanks for the tips from comments. I have took the "Largest Remainder" solution from the duplicate Post answer.
The code are:
def round_to_100_percent(number_set, digit_after_decimal=2):
"""
This function take a list of number and return a list of percentage, which represents the portion of each number in sum of all numbers
Moreover, those percentages are adding up to 100%!!!
Notice: the algorithm we are using here is 'Largest Remainder'
The down-side is that the results won't be accurate, but they are never accurate anyway:)
"""
unround_numbers = [x / float(sum(number_set)) * 100 * 10 ** digit_after_decimal for x in number_set]
decimal_part_with_index = sorted([(index, unround_numbers[index] % 1) for index in range(len(unround_numbers))], key=lambda y: y[1], reverse=True)
remainder = 100 * 10 ** digit_after_decimal - sum([int(x) for x in unround_numbers])
index = 0
while remainder > 0:
unround_numbers[decimal_part_with_index[index][0]] += 1
remainder -= 1
index = (index + 1) % len(number_set)
return [int(x) / float(10 ** digit_after_decimal) for x in unround_numbers]
Tested, seems work fine.