Python rounding percentage

I know how to round a number in Python, this is not a simple technical problem.

My problem is that rounding will make a set of percentages without adding up to 100% when, technically, they should.

For instance:

a = 1 b = 14 

I want to calculate 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 these numbers, I got

 1/15 = 6.66 14/15 = 93.33 

(I was engaged in flooring), which makes these two rooms not up to 100%.

In this case, we must make the ceiling 1/15, which is 6.67, and the floor - 14/15, which is 93.33. And now they make up to 100%. The rule in this case should be "rounding to the nearest number"

However, if we have a more complicated case, say 3 numbers:

 a = 1 b = 7 c = 7 

floor:

 1/15 = 6.66 7/15 = 46.66 7/15 = 46.66 

Does not add up to 100%.

ceiling:

 1/15 = 6.67 7/15 = 46.67 7/15 = 46.67 

does not add up to 100%.

Rounding (to the nearest number) matches the ceiling. Still not adding up to 100%.

So my question is what should I do to make sure that they all make up to 100% anyway.

Thanks in advance.

UPDATE: Thanks for the advice from the comments. I took the “Biggest Remaining” solution from a duplicate message reply.

The code:

 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 to work fine.

+5
source share
2 answers

As others commented, if your numbers are nice and round, as in your example, you can use the fractions module to maintain the accuracy of rational numbers:

 In [2]: from fractions import Fraction In [5]: a = Fraction(1) In [6]: b = Fraction(14) In [7]: a/(a+b) Out[7]: Fraction(1, 15) In [8]: a/(a+b) + (b/(a+b)) Out[8]: Fraction(1, 1) 

This clearly doesn't look good if you have really even fractions.

0
source

Welcome to floating IEEE.

The floating point numbers returned from math operations in python are approximate. At some values, the amount of interest will be more than 100.

You have two solutions: use fraction or decimal modules OR, you just don’t want them to add up to 100%.

-2
source

Source: https://habr.com/ru/post/1200138/


All Articles