Python 内置 round() 函数在 2.4 和 2.7 之间的变化

问题描述 投票:0回答:4

Python 中内置的 round() 函数在 2.4 和 2.7 之间有变化吗?

Python 2.4:

Python 2.4.6 (#1, Feb 12 2009, 14:52:44)

>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f,2)
1480.4000000000001

Python 2.7:

Python 2.7.1 (r271:86832, May 13 2011, 08:14:41)

>>> f = 1480.39499999999998181010596454143524169921875
>>> round(f, 2)
1480.39

有办法恢复 Python 2.4 的行为吗?

我知道正确的答案当然是使用

decimal
算术模块。不幸的是,鉴于时间限制,目前这可能不是一个选择。

更新

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

python floating-point python-2.7 floating-accuracy python-2.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 直接转换回浮点数,因此您将回到开始的地方。在最简单的形式中,Decimal 的
quantize
采用另一个 Decimal,它具有您真正想要的小数位数(将其视为舍入的模板)。如果您的数据绝对必须是浮点型,那么只有在完成所有小数计算后才转换回浮点型。

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


3
投票

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


1
投票
python 2.6 的新功能

页面中,我看到以下内容(参考PEP 3141):

Python 3.0 受Scheme 数字塔的启发,为数字类型添加了几个抽象基类。这些类作为数字模块向后移植到 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 中运行代码。


0
投票
round

函数也不“正确”,即不符合IEC 60559标准。试试这个:

print(round(2.25, 1))

您应该得到 
2.2

不是
2.3。这个问题在 3.# 版本中得到了修复(我只测试了 3.5 及以上版本)。
    

© www.soinside.com 2019 - 2024. All rights reserved.