0

我正在研究 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

为什么第一种,尤其是第二种情况会失败?

4

6 回答 6

7

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

所以它被四舍五入

于 2012-09-04T07:41:16.443 回答
2

这可能是答案的一部分:

>>> a*.1
20.325000000000003
>>> a/10
20.325

有关如何实现 IEEE 754 舍入,请参阅 @gnibbles 说明。

于 2012-09-04T07:43:14.700 回答
1

我不知道为什么这些情况不能按预期工作的具体细节,但如果你想对你的浮点数进行严格的准确性,请使用像decimal 模块这样的东西。

于 2012-09-04T07:39:06.463 回答
0

没有失败。看看每个程序员应该知道的关于浮点运算的知识

于 2012-09-04T07:40:55.250 回答
0

您可以使用 printf 查看发生了什么

 print '%0.20f'%20.325
 20.32499999999999928946
于 2012-09-04T07:43:18.377 回答
0

Python 文档round()指向答案。基本上,浮点数不能准确地表示某些数字。例如,0.1最终看起来像0.10000000000000001. 这种不精确性有时会导致意想不到的结果。使用浮点数在给定的容差范围内进行计算确实非常困难。计算在您的情况下有效的原因0.1 * a是因为它在您所需的舍入方向上略有偏差。

如果你真的需要精度,你应该考虑使用Decimal 模块。使用十进制数字也可能是一件苦差事,但它确实可以更轻松地获得所需的精度。

于 2012-09-04T07:44:17.790 回答