Python3四舍五入到最近的偶数

21

Python3.4 四舍五入到最近的偶数(在平局情况下)。

>>> round(1.5)
2
>>> round(2.5)
2

但只有在四舍五入到整数时,它才似乎这样做。

>>> round(2.75, 1)
2.8
>>> round(2.85, 1)
2.9
在上面的最后一个例子中,当四舍五入到最接近的偶数时,我本来期望得到2.8作为答案。
为什么这两种行为之间会有差异呢?

5
这个东西的山寨品太多了,几乎令人痛苦。 - The Paramagnetic Croissant
1
@AirThomas,这是Python3特定的问题,因为据我所知,round()函数只在Python3中开始四舍五入到最近的偶数。 - Alex Couper
@AlexCouper:即使是偶数舍入改变了您的预期,但您所预期和观察到的差异仍然可以通过所有这些重复来解释。 - Martijn Pieters
@user3477950 抱歉 - 写这篇文章时我找不到任何相关信息,但在看到你的评论后,我找到了https://dev59.com/X2gv5IYBdhLWcg3wI9Wg。 - Alex Couper
如果你的问题仅仅是“为什么在Python 3.x中会发生这种情况?”,那么已有的答案可以回答这个问题,但如果你真的想知道如何在Python 3.x中获得预期的四舍五入,则答案是“使用decimal模块”。 - smci
3个回答

33

浮点数只是近似值;2.85 无法被精确表示:

>>> format(2.85, '.53f')
'2.85000000000000008881784197001252323389053344726562500'

这个数略大于2.85。

0.5和0.75可以用二进制小数精确表示(分别为1/2和1/2+1/4)。

round()函数明确记录了这一点:

注意:对浮点数进行四舍五入的行为可能令人惊讶:例如,round(2.675, 2)返回2.67而不是期望的2.68。这并非错误,而是因为大多数十进制小数不能完全精确地表示为浮点数。有关更多信息,请参见浮点运算:问题与限制


啊 - 因此 round(2.25, 1) 确实按预期向下舍入为 2.2。 - Alex Couper
这是一个有用的工具,详细解释了浮点数是如何存储的。请访问以下链接:http://www.h-schmidt.net/FloatConverter/IEEE754.html - ElmoVanKielmo

1

Martijn说得很对。如果你想要一个可以将整数四舍五入到最接近的偶数的函数,那么我会选择这个:

def myRound(n):
    answer = round(n)
    if not answer%2:
        return answer
    if abs(answer+1-n) < abs(answer-1-n):
        return answer + 1
    else:
        return answer - 1

这段代码的意图是什么?对于一个整数输入 n,它似乎只返回 n - n % 2 - Mark Dickinson
@MarkDickinson:这是针对“int”输入的情况。但是,对于浮点数输入,它会四舍五入到最接近的偶数整数。 - inspectorG4dget
@inspectorG4dget 但是Python的round()函数已经四舍五入到最近的偶数了,所以在round()之后做的任何操作都是不必要的。 - Andreas Magnusson
不对,@AndreasMagnusson,round(2.6) == 3,它只在平局时向最接近的偶数四舍五入。 - rsalmei
@rsalmei: 没错 - inspectorG4dget

0

回答标题... 如果您使用 int(n),它将朝零截断。如果结果是奇数,则加一:

n = 2.7     # your whatever float
result = int(n)
if (result & 1):     
    result += 1

更新:是的,这里存在一个负数的错误。还有一个关于已经有整数值的数字的bug。留作作业给你 :)


我从未见过有人使用 & 1 而不是 % 2 来检查一个数字是否为偶数... 没有周围的上下文,我甚至不确定那是你在做什么。我会认为你正在进行某种标志比较或其他操作。 - ArtOfWarfare
@MarkDickinson:感谢您指出这个错误;)您是正确的,Alex在他的脑海中有不同的想法。 - pepr
@pepr 在像C这样的语言中,它们编译成相同的内容,在Python这样的可重载语言中则不等价。 - wizzwizz4
1
@pepr,实现非常好,但是您犯了一个错误。 您正确地编写了“如果结果不是偶数”,但实现的是“如果结果不是(result&1)”,即“如果结果不是奇数”。 只需删除 “not” 即可实现很好的“四舍五入到最近的偶数”函数。 - rsalmei
@rsalmei:你说得对。(我的英语有点奇怪。 :) (result & 1) 获取最低位。如果它被设置为一,则该值为奇数。 - pepr
显示剩余3条评论

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