在numpy中进行地板除法的结果很奇怪。

13

我遇到了一个np.float32或np.float64的地板除法结果,但我不理解。

我在Python 3.6.7中使用numpy 1.15.4。

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

我知道,我可以通过使用abs()之类的方法来解决问题,但是为什么我一开始会得到一个“-0.0”而不是“0.0”呢?


1
https://dev59.com/mm855IYBdhLWcg3w6IzV#4083431 - Scott Boston
2
可能是Python中的负零重复问题。 - Matthieu Brucher
3
@DDS,我不完全确定这是否解决了提问者的疑虑。 - Scott Boston
3
@DDS 这个链接没有解释清楚一个事实,即普通的Python等价表达式 0.0//1 == 0.0 而不是 -0.0 - meowgoesthedog
2
@ScottBoston 这是相关的,但我认为它并没有解释为什么 (+0.0) // 1 == -0.0... 特别是考虑到这是 NumPy 中发生的事情,而不是 Python 浮点数值。 - jdehesa
显示剩余3条评论
1个回答

9

我怀疑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)

我进一步研究了这个问题,以下是当div为零时,Python的divmod如何处理浮点数的方式(链接):

/* 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 版本中得到修复。您可以在这里查看发布说明。

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