Разное поведение раундов для Python в float и numpy.float64 - PullRequest
0 голосов
/ 12 ноября 2018

Я наткнулся на сбой теста, вызванный точностью с плавающей запятой, и пытаюсь понять это.

Вкратце: Python3 round возвращает различное значение в зависимости от того, является ли тип float или numpy.float64, хотя я думал, что float==double==float64 и оба Python 3 и NumPy должен округляться ближе к четному.

Вот пример:

npVal = np.float64(435)/100
pyVal = 435/100
print(round(npVal,1))             // 4.4
print(round(pyVal,1))             // 4.3
print(round(np.float64(pyVal),1)) // 4.4
print(round(float(npVal),1))      // 4.3

Я понимаю, что 4.35 и 4.4 могут быть не совсем точно представлены в double, но почему numpy round отличается от Python, хотя они оба используют одни и те же типы данных и задают схожую функцию? Я использовал явное деление, чтобы избежать ошибок округления ввода.

Я точно не знаю, является ли значение double для 4.35 чуть более или менее, поэтому я не могу сказать , какая из этих реализаций является (может быть?) Неправильной.

Есть похожий вопрос: Странное поведение numpy.round

Там было отмечено, что NumPy «округляет до ближайшего четного значения» и «изменилось поведение между Python 2 и Python 3; Python 3 ведет себя так же, как NumPy».

Так что оба должны делать то же самое и округлять до ближайшего четного значения. Так что , если 4.35 будет точным числом с плавающей запятой, 4.4 будет правильным ответом и должен быть возвращен обоими.

1 Ответ

0 голосов
/ 12 ноября 2018

Вычисление 435/100 в базовых 64-разрядных двоичных двоичных данных IEEE-754 4.3499999999999996447286321199499070644378662109375.

Когда это значение округляется до ближайшего десятичного числа с одной цифрой после десятичной точки, результат должен быть«4,3».Округление Python для этого случая представляется правильным.

Для numpy.round документация относится к numpy.around.Документация для этого гласит: «Результаты также могут быть неожиданными из-за… ошибок, возникающих при масштабировании по степеням десяти». Таким образом, возможно, что numpy.round не вычисляет правильное преобразование 4,3499999999999996447286321199499070644378662109375 в десятичную, носкорее выполняет 64-битное двоичное умножение с плавающей точкой на 10, что дает ровно 43,5 из-за округления с плавающей точкой, а затем numpy.round округляет это до 44 и форматирует как «4.4».

Таким образом, numpy.round не является правильной процедурой округления.

...