Странный результат разделения пола в NumPy

Я наткнулся на результат деления пола np.float32 или np.float64, который я не понимаю

Я использую NumPy 1.15.4 в Python 3.6.7

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

Я знаю, что я могу обойти abs() и тому подобное, но почему я получаю "-0.0" вместо "0.0" в первую очередь??

1 ответ

Решение

Я подозреваю, что 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.])

Питона divmod Функция, кажется, обрабатывает это правильно, поэтому они должны использовать разные алгоритмы:

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

Я рассмотрел это немного подробнее, и вот как работает divmod в python для чисел с плавающей запятой, когда 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. Вы можете увидеть примечания к выпуску здесь.

Другие вопросы по тегам