Python浮点数舍入误差:117.285四舍五入为117.28而不是117.29。

6

我正在使用Python 2.7,并且我拥有的代码如下:

a = 10.5 * 22.34 / 2.0
print "%.2f" % a

我预期的结果是117.29,但显示为117.28,该如何解决问题?

3个回答

12

如果Python使用64位IEEE-754二进制浮点类型,则它使用的精确值将是:

117.284999999999996589394868351519107818603515625

......很明显比117.28和117.29的中间点要低。这可能就是正在发生的事情。

另一个选项是Python正在使用银行家舍入法

如果精确的小数值对您很重要,您可能希望考虑改用decimal


有趣的是...尝试上述代码(v2.6.4),print a 输出 "117.285"。更奇怪的是,print "%.4f" % 117.285 输出 "117.2850"。 - Nathan Ernst
@NathanErnst:如果没有任何东西,它可能使用一些默认精度 - 当您指定4个有效数字时,那么它就是117.2850... - Jon Skeet
1
Python使用平台double作为其浮点类型,而117.285的确就在其下面。 (参见'%.18f'%117.285。) 此外,Python还使用银行家舍入法,您可以通过比较'%.0f'%0.5'%.0f'%1.5来了解。 - Thomas Wouters

8

Skeet 先生给出了正确的答案,下面是他所提到的使用decimal模块的示例:

import decimal
a = decimal.Decimal('117.285')
rounded = a.quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_HALF_UP)
print rounded
# 117.29
repr(rounded)
# "Decimal('117.29')"

2
如果你想要一个简单的解决方案并且不关心性能,你可以使用像这样的函数将其转换为整数、四舍五入并再次转换为浮点数:
def round_exact(number, decimal_places=0):
    """Round the number to the given number of decimal places by converting to 
    and from integers to avoid floating point error."""
    factor = 10**(decimal_places + 1)
    rounded_int = int(number * factor)
    if rounded_int % 10 >= 5:
        # Round up
        return (int(rounded_int//10) + 1) / float(factor//10)
    # Round down
    return int(rounded_int//10) / float(factor//10)

十年过去了,问题依然存在且依然有效。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接