在numpy中地板划分的奇怪结果



>我偶然发现了 np.float32 或 np.float64 的地板划分结果,我不明白

我在 Python 1.15.4 中使用 numpy 3.6.7

>>> import numpy as np
>>> np.float32(0)//1
-0.0

我知道,我可以通过 abs() 等解决方法,但为什么我首先得到"-0.0"而不是"0.0"?

我怀疑 numpy 使用divmod 函数来计算地板分割,导致这种情况的线在这里:

/* if div is zero ensure correct sign */
floordiv = (a / b > 0) ? 0.0@c@ : -0.0@c@;

例:

>>> a = np.zeros(1)
>>> b = 1
>>> np.where(a/b > 0, 0.0, -0.0)
array([-0.])

Python 的 divmod 函数似乎可以正确处理这个问题,因此它们必须使用不同的算法:

>>> divmod(0.0,1)
(0.0, 0.0)
>>> divmod(-0.0,1)
(-0.0, 0.0)

我对此进行了更多的研究,以下是 python 的divmod 在div 为零时如何用于浮点数(链接):

/* div is zero - get the same sign as the true quotient */
floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */

copysign()定义为:

double
copysign(double x, double y)
{
    /* use atan2 to distinguish -0. from 0. */
    if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
        return fabs(x);
    } else {
        return -fabs(x);
    }
}

所以Python能够做到这一点而numpy不能做到这一点的原因是Python使用atan2()来区分-0.0+0.0

更新:此问题将在 numpy 的 1.17.0 版本中修复。您可以在此处查看发行说明。

最新更新