Python中的四舍五入是如何工作的?

5

我对 Python 中的舍入方式有点困惑。
请问有人能够解释一下为什么 Python 的行为会像这样吗?

示例:

>>> round(0.05,1) # this makes sense
0.1
>>> round(0.15,1) # this doesn't make sense! Why is the result not 0.2?
0.1

同样适用于:

>>> round(0.25,1) # this makes sense
0.3
>>> round(0.35,1) # in my opinion, should be 0.4 but evaluates to 0.3
0.3
编辑: 总的来说,Python 有可能将数字向下取整,而不是向上取整。那么我是否可以理解,唯一可能发生的“异常”就是 Python 向下取整?或者它也可能因为存储方式而出现“异常”向上取整吗?(我还没有遇到过 Python 在我预期向下取整时向上取整的情况)

相关:print '%.20f %.20f %.20f'%(.15, .25, .35) - Robᵩ
@Rob_phi:不相关的问题:即使在我的地址栏中显示URL时[当我点击你的用户名],你的下标符号phi也被正确地呈现出来了...怎么做到的?!? - gariepy
@gariepy 如果你将URL复制到文本编辑器中,它会显示为http://stackoverflow.com/users/8747/rob%E1%B5%A9 - 一些浏览器如Chrome会在URL栏中呈现转义的Unicode字符。 - Galax
@Galax:很酷,谢谢! - gariepy
1
Python 2 还是 Python 3?请注意,半路情况的行为是不同的(对于实际的、真正的半路情况)。例如,在 Python 2 中,round(1.25, 1) 将给出 1.3,而在 Python 3 中它会给出 1.2 - Mark Dickinson
3个回答

12

这其实是有意设计的。根据Python的文档

对于浮点数,round() 的行为可能会令人惊讶:例如,round(2.675, 2) 得到的结果是2.67,而不是预期的2.68。这不是一个bug:这是因为大多数十进制小数无法准确地表示为浮点数。


5
是的,特别是“0.15”在内部表示为“0.1499999999999999944488848768742172978818416595458984375”,而“0.35”则为“0.34999999999999997779553950749686919152736663818359375”。这两个数字都合理地向下取整。 - Kevin
一般来说,它有可能被向下舍入而不是向上舍入。所以唯一的“异常”情况就是它被舍入到了较小值?或者由于存储方式,它也可能出现“异常”地向上舍入吗?(我还没有找到一个期望向下舍入却被向上舍入的案例。) - Jonas Kaufmann

8

我觉得你需要使用 decimal 模块:

from decimal import *
x = Decimal('0.15')
print x.quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)

输出:

0.2

1
@JonasKaufmann:如果你需要精确的十进制表示,就像你所说的那样,这是正确的答案。此外,这也是为什么Cobol被发明出来的原因。而且,它仍在使用中。:( - gariepy

4
作为示例,这里有一个四舍五入的案例:
>>> round(0.0499999999999999999,1)
0.1

在这种情况下,“9”数量为17是导致此行为的最小数量。这是因为 0.0499999999999999999 的内部表示形式是 0.05000000000000000277555756156289135105907917022705078125

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