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

4 投票
4 回答
3337 浏览
提问于 2025-04-17 08:44

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这个算术模块。不过,考虑到时间限制,这可能现在不太可行。

更新

为了提供一些背景信息,我正在比较两个系统中的数值,其中一个使用十进制表示,另一个使用浮点数。这可能(也可能不)是两个系统之间的一个合理差异,需要进一步检查,所以我会咨询用户,并在“报告”阶段处理这个问题,而不是在我从系统获取数据的时候。

4 个回答

1

Python 2.6 的新特性 页面上,我看到以下内容(提到 PEP 3141):

Python 3.0 引入了几个抽象基类,用于数字类型,这些类受到了 Scheme 数字塔的启发。这些类被移植到了 2.6 版本,作为 numbers 模块。

...

在 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 中运行代码。

3

可能不行,因为Python 2.4实际上返回了一个错误的结果。当你要舍去的数字小于5时,正确的做法应该是向下舍入,也就是把它变成更小的数字。

如果你能具体描述一下你需要的行为,我们或许可以想出其他的方法来解决这个问题。

6

你第一个问题的答案是:是的,round 在 Python 2.7 中已经修复了。

你第二个问题的答案是:我不太确定,除非真的去用早期的 Python(2.6 应该还会有 2.4 的表现)。在这个特定的情况下,你的值和 1480.395 是没什么区别的,而 1480.395(对我们这些十进制的人来说)会四舍五入到 1480.40。所以我想你可以先四舍五入到比你想要的多一位小数,然后把它变成字符串,再从中得到一个 Decimal……不过抱歉,我想不出不涉及 Decimal 的其他方法。如果我想到了什么(在别人发出更好的建议之前),我会回来修改。

(不过,真的,使用 Decimal 有那么难吗?)

编辑: 这里有一个使用 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,那个 Decimal 代表你真正想要的小数位数(可以把它想象成一个四舍五入的模板)。如果你的数据必须是浮点数,那么在所有 Decimal 计算完成后再转换回浮点数。

最后:我不确定这是否涵盖了 Python 2.4 浮点数行为中的所有奇怪情况。如果你依赖于 Python 2.4 的确切行为,可能没有其他办法可以替代运行在 Python 2.4 上。我上面描述的只是更接近人类风格的四舍五入的一步。

撰写回答