Python 中内置的 round() 函数在 2.4 和 2.7 之间有变化吗?
Python 2.4.6 (#1, Feb 12 2009, 14:52:44)
>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f,2)
1480.4000000000001
Python 2.7.1 (r271:86832, May 13 2011, 08:14:41)
>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f, 2)
1480.39
有办法恢复 Python 2.4 的行为吗?
我知道正确的答案当然是使用
decimal
算术模块。不幸的是,鉴于时间限制,目前这可能不是一个选择。
更新
对于上下文,我正在比较两个系统中的值,其中一个使用十进制表示,另一个使用浮点表示。这可能(或可能不是)系统之间的合法差异需要进一步检查,因此我将咨询用户并在“报告”级别处理它,而不是在我从系统获取数据时处理它.
第一个问题的答案是:是的,
round
已在Python 2.7中修复。
你的第二个问题的答案是:我不确定,缺乏实际使用早期的Python(2.6应该仍然表现出2.4的行为)。在这种特殊情况下,您的值与 1480.395 没有区别,并且 1480.395(对于我们以 10 为基数的人类来说)四舍五入到 1480.40。所以我想你可以尝试首先舍入到超出你真正想要的地方,将其转换为字符串,然后从中得到一个小数......但是抱歉,我想不出任何不涉及小数的东西。如果我想到了什么(在其他人发布更好的内容之前),我会回来编辑。
(但是说真的,Decimal 有那么难用吗?)
编辑: 这是如何使用十进制的示例:
>>> from decimal import Decimal
>>> f = Decimal('1480.395')
>>> f.quantize(Decimal('0.00'))
Decimal('1480.40')
>>> float(Decimal('1480.40'))
1480.4
一些注意事项:
Python 2.7 允许您使用浮点数作为 Decimal 的输入。 不要这样做,因为您会回到起点。另外,不要在 Decimal 上使用内置
round
函数,因为该函数会将您的 Decimal 直接转换回浮点数,因此您将回到开始的地方。在最简单的形式中,Decimal 的 quantize
采用另一个 Decimal,它具有您真正想要的小数位数(将其视为舍入的模板)。如果您的数据绝对必须是浮点型,那么只有在完成所有小数计算后才转换回浮点型。
最后:我不确定这是否涵盖了 Python 2.4 浮动行为中所有可能的奇怪情况。如果您完全依赖 Python 2.4 的行为,那么在 Python 2.4 上运行可能是无可替代的。我上面所描述的只是离人类风格舍入更近了一步。
如果您可以描述您需要的确切行为,我们也许可以创建替代方法。
页面中,我看到以下内容(参考PEP 3141):
Python 3.0 受Scheme 数字塔的启发,为数字类型添加了几个抽象基类。这些类作为数字模块向后移植到 2.6。...
在 Python 3.0 中,PEP 稍微重新定义了现有的内置函数 round()、math.floor()、math.ceil(),并添加了一个新的内置函数 math.trunc(),该函数已向后移植到 Python 2.6。 math.trunc() 向零舍入,返回函数参数和零之间最接近的积分。
python 2.7 中的新增功能round() 函数现在也可以正确舍入。并且,感谢 @mark-dickinson 评论,在
是的,变化发生在 python 2.7 中。这可以通过检查 python 2.6 中的行为是否仍然是旧的来验证:
Python 2.6.7 (r267:88850, Aug 11 2011, 12:18:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f, 2)
1480.4000000000001
在我的 Linux 发行版中,我仍然可以访问 python 2.6 和 python 2.7,也许您也可以使用;所以,如果你想要旧的行为,也许你可以尝试在 python 2.6 中运行代码。
round
函数也不“正确”,即不符合IEC 60559标准。试试这个:
print(round(2.25, 1))
您应该得到
2.2
和
不是
2.3
。这个问题在 3.# 版本中得到了修复(我只测试了 3.5 及以上版本)。