我正在研究 Python 中的舍入浮点数,以下行为似乎很奇怪:
代码:
a = 203.25
print '%.2f'%(a/10.)
print '%.2f'%(round(a/10., 2))
print '%.2f'%(0.1*a)
输出:
20.32
20.32
20.33
为什么第一种,尤其是第二种情况会失败?
我正在研究 Python 中的舍入浮点数,以下行为似乎很奇怪:
代码:
a = 203.25
print '%.2f'%(a/10.)
print '%.2f'%(round(a/10., 2))
print '%.2f'%(0.1*a)
输出:
20.32
20.32
20.33
为什么第一种,尤其是第二种情况会失败?
http://en.wikipedia.org/wiki/Rounding#Round_half_to_even
Round half to even
一个偏少的平局规则是round half to even,即:如果 y 的分数为 0.5,则 q 是最接近 y 的偶数。因此,例如,+23.5 变为 +24,+24.5 也是如此;而-23.5 变成-24,-24.5 也是如此。
这种方法对称地处理正负值,因此没有符号偏差。更重要的是,对于 y 值的合理分布,四舍五入的数字的预期(平均值)与原始数字的预期(平均值)相同。然而,这条规则会为偶数引入趋向零的偏差,而为奇数引入趋向无穷大的偏差。
这种四舍五入法的变体也称为无偏舍入、收敛舍入、统计学家舍入、荷兰式舍入、高斯舍入、奇偶舍入或银行家舍入,广泛用于簿记。
这是 IEEE 754 计算函数和运算符中使用的默认舍入模式。
>>> "%.2f"%20.325
'20.32'
>>> "%.2f"%20.335
'20.34'
>>> "%.2f"%20.345
'20.34'
>>> "%.2f"%20.355
'20.36'
所以真正的问题应该是为什么第三种情况会失败?
203.25
可以用浮点表示精确地表示,但是0.1
不能,结果证明它比0.1
>>> 0.1*203.25
20.325000000000003
所以它被四舍五入
这可能是答案的一部分:
>>> a*.1
20.325000000000003
>>> a/10
20.325
有关如何实现 IEEE 754 舍入,请参阅 @gnibbles 说明。
我不知道为什么这些情况不能按预期工作的具体细节,但如果你想对你的浮点数进行严格的准确性,请使用像decimal 模块这样的东西。
没有失败。看看每个程序员应该知道的关于浮点运算的知识。
您可以使用 printf 查看发生了什么
print '%0.20f'%20.325
20.32499999999999928946
Python 文档round()
指向答案。基本上,浮点数不能准确地表示某些数字。例如,0.1
最终看起来像0.10000000000000001
. 这种不精确性有时会导致意想不到的结果。使用浮点数在给定的容差范围内进行计算确实非常困难。计算在您的情况下有效的原因0.1 * a
是因为它在您所需的舍入方向上略有偏差。
如果你真的需要精度,你应该考虑使用Decimal 模块。使用十进制数字也可能是一件苦差事,但它确实可以更轻松地获得所需的精度。