Python 百分比四舍五入

7 投票
2 回答
3447 浏览
提问于 2025-04-18 17:02

我知道怎么在Python中对数字进行四舍五入,这不是一个简单的技术问题。

我的问题是,四舍五入会导致一组百分比加起来不等于100%,而从技术上讲,它们应该加起来等于100%。

举个例子:

a = 1
b = 14

我想计算a在(a + b)中的百分比,以及b在(a + b)中的百分比。

答案应该是

a/(a + b) = 1/15 
b/(a + b) = 14/15

当我尝试对这些数字进行四舍五入时,我得到了

1/15 = 6.66 
14/15 = 93.33 

(我当时是向下取整),这导致这两个数字加起来不等于100%。

在这种情况下,我们应该对1/15进行向上取整,得到6.67,对14/15进行向下取整,得到93.33。这样它们加起来就等于100%了。在这种情况下的规则应该是“四舍五入到最近的数字”。

但是,如果我们有一个更复杂的情况,比如3个数字:

a = 1
b = 7
c = 7

向下取整:

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

加起来不等于100%。

向上取整:

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

也加起来不等于100%。

四舍五入(到最近的数字)和向上取整是一样的,仍然加起来不等于100%。

所以我的问题是,我应该怎么做才能确保在任何情况下它们都加起来等于100%。

提前谢谢你们。

更新:
感谢评论中的建议。我已经从重复帖子答案中采用了“最大余数”解决方案。

代码是:

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]

测试过了,似乎运行得很好。

2 个回答

-2

欢迎来到IEEE浮点数的世界。

在Python中,数学运算返回的浮点数其实是近似值。有些情况下,几个百分比加起来可能会超过100%。

你有两种解决办法:要么使用fractiondecimal模块,要么就不要求它们加起来等于100%。

0

正如其他人所说,如果你的数字像例子中那样整齐划一,你可以使用fractions模块来保持有理数的准确性:

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)

不过,如果你有一些很奇怪的分数,这样看起来就不太好看了。

撰写回答