4

Python 中内置的 round() 函数是否在 2.4 和 2.7 之间发生了变化?

蟒蛇2.4:

Python 2.4.6 (#1, Feb 12 2009, 14:52:44)
[GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f,2)
1480.4000000000001
>>>

蟒蛇 2.7:

Python 2.7.1 (r271:86832, May 13 2011, 08:14:41)
[GCC 3.4.6 20060404 (Red Hat 3.4.6-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f, 2)
1480.39
>>>

无论如何要恢复 Python 2.4 的行为吗?

我知道正确的答案当然是使用十进制算术模块。不幸的是,鉴于时间限制,目前这可能不是一个选择。

更新

对于上下文,我正在比较两个系统中的值,其中一个使用十进制表示,另一个使用浮点表示。这可能(或可能不是)需要进一步检查的系统之间的合法差异,因此我将咨询用户并在“报告”级别处理它,而不是在我从系统获取数据时.

谢谢你的帮助!

4

4 回答 4

6

第一个问题的答案是:是的,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 立即转换回浮点数,因此您将回到开始的位置。在最简单的形式中,Decimalquantize采用另一个具有您真正想要的小数位数的 Decimal(将其视为舍入的模板)。如果您的数据绝对必须是浮点数,那么只有在完成所有小数计算后才转换回浮点数。

最后:我不确定这是否涵盖了 Python 2.4 浮动行为中所有可能的奇怪极端情况。如果您完全依赖Python 2.4 的行为,则可能无法替代在 Python 2.4 上运行。我上面描述的只是更接近人类风格的四舍五入。

于 2011-12-20T22:50:03.963 回答
3

可能不是因为 Python 2.4 实际上返回了不正确的结果。由于您要舍入严格小于 5 的数量,因此应将正确的结果舍入。

如果您可以描述您需要的确切行为,我们也许可以创建一种替代方法。

于 2011-12-20T22:48:21.293 回答
1

python 2.6 中的新增功能页面中,我看到以下内容(参考PEP 3141):

Python 3.0 为受 Scheme 的数字塔启发的数字类型添加了几个抽象基类。这些类作为 numbers 模块向后移植到 2.6。

...

在 Python 3.0 中,PEP 略微重新定义了现有的内置函数 round()、math.floor()、math.ceil(),并添加了一个新的内置函数 math.trunc(),它已向后移植到 Python 2.6。math.trunc() 向零舍入,返回函数参数和零之间最接近的积分。

并且,感谢@mark-dickinson 评论,在 python 2.7 中的新增功能页面中,可以找到以下文本:

round() 函数现在也已正确舍入。

所以是的,变化发生在 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 中运行代码。

于 2011-12-20T22:52:14.437 回答
0

也许我在其他回复中错过了这一点,但实际上round最后一个 Python 2.# 版本(版本 2.7.18)的功能也不“正确”,即不符合 IEC 60559 标准。尝试这个:

print(round(2.25, 1))

你应该得到2.2不是 2.3。这在 3.# 版本中得到了修复(我只测试了 3.5 以后的版本)。

于 2021-05-17T09:53:19.443 回答