Python 2中的Python 3舍入行为

for*_*ord 21 python

在Python 2.x中,内置函数round具有以下行为:

如果两个倍数相等,则舍入远离0(因此,例如,round(0.5)为1.0,round(-0.5)为-1.0)

在Python 3.x中,这已经变为更常见的:

如果两个倍数相等,则向均匀选择进行舍入(例如,圆形(0.5)和圆形(-0.5)都是0,圆形(1.5)是2).

有没有一种简单的方法可以在Python 2.x中获得这种行为?不幸的是,该future_builtins模块不包括此内容.也许还有另一个类似的模块我还没找到?或者,将Python 3.x函数引入Python 2.x的另一种方法是什么?

显然,我可以编写一个产生所需行为的新函数,但是如果存在使用实际Python 3.x函数的解决方案,我会更加好奇,以避免添加不必要的复杂性和代码来维护.

Use*_*ser 6

Python 3 转入 Python 2

该函数可以如下所示:

def py3round(f):
    if abs(round(f)-f) == 0.5:
        return 2.0*round(f/2.0);
    return round(f)

# Python 3            apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ...
>>> ' '.join(map(str, map(int, [round(i * 0.25) for i in range(-20, 20)])))
'-5 -5 -4 -4 -4 -4 -4 -3 -3 -3 -2 -2 -2 -2 -2 -1 -1 -1 0 0 0 0 0 1 1 1 2 2 2 2 2 3 3 3 4 4 4 4 4 5'
# Python 2            apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ...
>>> ' '.join(map(str, map(int, [py3round(i * 0.25) for i in range(-20, 20)])))
'-5 -5 -4 -4 -4 -4 -4 -3 -3 -3 -2 -2 -2 -2 -2 -1 -1 -1 0 0 0 0 0 1 1 1 2 2 2 2 2 3 3 3 4 4 4 4 4 5'
Run Code Online (Sandbox Code Playgroud)

让我澄清一下 round 的作用bltinmodule.c

if hasattr(args[0], '__round__'):
    return args[0].__round__(*args[1:])
else: 
    raise TypeError("type %.100s doesn't define __round__ method")
Run Code Online (Sandbox Code Playgroud)

所以 round 实际上几乎什么也没做。这取决于传递给它的对象。这导致floatobject.c功能static PyObject *double_round(double x, int ndigits)

z = round(y);
if (fabs(y-z) == 0.5)
    /* halfway between two integers; use round-half-even */
    z = 2.0*round(y/2.0);
Run Code Online (Sandbox Code Playgroud)

我在上面的函数中使用了这些行的知识。

Python 2 转入 Python 3

我认为你需要编写一个新函数。

def python2round(f):
    if round(f + 1) - round(f) != 1:
        return f + abs(f) / f * 0.5
    return round(f)
Run Code Online (Sandbox Code Playgroud)

i + 0.5if 语句处理和被四舍五入到不同方向的情况i + 1.5= 为偶数和二等分。在这种情况下,舍入是从零开始的。

# in Python 2          apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ...
>>> ' '.join(map(str, map(int, [round(i * 0.25) for i in range(-20, 20)])))
'-5 -5 -5 -4 -4 -4 -4 -3 -3 -3 -3 -2 -2 -2 -2 -1 -1 -1 -1 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5'
# in Python 3          apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ...
>>> ' '.join(map(str, map(int, [python2round(i * 0.25) for i in range(-20, 20)])))
'-5 -5 -5 -4 -4 -4 -4 -3 -3 -3 -3 -2 -2 -2 -2 -1 -1 -1 -1 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5'
Run Code Online (Sandbox Code Playgroud)

您是否需要使用第二个参数进行舍入的解决方案ndigits


ber*_*eal 5

除非您介意麻木的依赖关系,numpy.around否则可以执行以下操作:

>>> from numpy import around
>>> around(0.5)
0
>>> around(-0.5)
-0
>>> around(1.5)
2.0
Run Code Online (Sandbox Code Playgroud)

  • +1如果您碰巧碰到numpy说谎,这是一个很好的解决方案。 (2认同)