Почему sin (180) не равен нулю при использовании python и numpy?
кто-нибудь знает, почему ниже не равна 0?
import numpy as np
np.sin(np.radians(180))
или:
np.sin(np.pi)
когда я ввожу его в python, он дает мне 1.22 e-16.
2 ответов
количество π
не может быть представлен точно как число с плавающей точкой. Итак,np.radians(180)
не дает π
, это дает вам 3.1415926535897931
.
и sin(3.1415926535897931)
на самом деле что-то вроде 1.22e-16
.
Итак, как вы справляетесь с этим?
вы должны разработать или, по крайней мере, угадать соответствующие абсолютные и/или относительные границы ошибок, а затем вместо x == y
вы пишете:
abs(y - x) < abs_bounds and abs(y-x) < rel_bounds * y
(это также означает, что вы должны организовать ваши вычисления так, чтобы относительная ошибка была больше относительно y
, чем x
. В вашем случае, потому что y
постоянный 0
, это тривиально - просто сделайте это задом наперед.)
Numpy предоставляет функцию, которая делает это для вас во всем массиве,allclose
:
np.allclose(x, y, rel_bounds, abs_bounds)
(это на самом деле проверки abs(y - x) < abs_ bounds + rel_bounds * y)
, но это почти всегда достаточно, и вы можете легко реорганизовать свой код, когда это не так.)
в вашей дело:
np.allclose(0, np.sin(np.radians(180)), rel_bounds, abs_bounds)
Итак, как вы знаете, что правильные границы? Нет способа научить вас достаточному анализу ошибок в ответе SO. распространения неопределенности в Википедии дает обзор высокого уровня. Если у вас действительно нет подсказки, вы можете использовать значения по умолчанию, которые являются 1e-5
относительная и 1e-8
абсолютная.
проблема в том, что это не ошибка округления pi. Обратите внимание, что проблема не возникает для Косинуса:
In [2]: np.sin(np.pi)
Out[2]: 1.2246467991473532e-16 != 0.
In [3]: np.cos(np.pi)
Out[3]: -1.0 == -1.
проблема гораздо больше ... сложный. Это связано с точностью pi внутри процессора. Это было обнаружено и объяснено здесь: https://randomascii.wordpress.com/2014/10/09/intel-underestimates-error-bounds-by-1-3-quintillion/