Numpy - квадратный корень из -1 оставляет небольшую реальную часть

возможно, это алгоритмическая проблема, но следующий кусок кода

numpy.power((-1+0j),0.5)

производит следующий вывод

(6.1230317691118863e-17+1j)

аналогичные выражения, например,numpy.power(complex(-1),.5) даст тот же результат, однако - numpy.sqrt(complex(-1)) дает ожидаемый результат 1j. Очевидно, что результат не должен иметь реальной части, поэтому я упускаю что-то важное или мне нужно сообщить об этом numpy dev.

в случае, если кто-нибудь спросит, нет, я не могу круглые прочь реальную часть (мне нужна полная точность для этого расчета), и да, мне нужно использовать функцию питания.

3 ответов


это побочный эффект реализации numpy.power() для комплексных чисел. Stdlib демонстрирует ту же проблему.

>>> numpy.power(-1+0j, 0.5)
(6.123233995736766e-17+1j)
>>> cmath.exp(cmath.log(-1)/2)
(6.123233995736766e-17+1j)

что происходит, так это то, что квадратный корень из -1 вычисляется как exp (I phase/2), где фаза (из -1)примерно π. На самом деле,

>>> import cmath, math
>>> z = -1+0j
>>> cmath.phase(z)
3.141592653589793
>>> math.cos(_/2)
6.123233995736766e-17

это показывает, что фаза -1 равна π только до нескольких 1e-17; фаза, разделенная на 2, также приблизительно равна π / 2, а ее Косинус-только приблизительно 0, следовательно, ваш результат (реальная часть вашего результата-этот Косинус).

проблема в конечном счете исходит из того, что существует только фиксированное, конечное число чисел с плавающей запятой. Число π не входит в список чисел с плавающей запятой и поэтому может быть представлено только приблизительно. π/2 также не может быть точно представлен, так что действительная часть квадратного корня -1 является Косинусом приближения с плавающей запятой π / 2 (следовательно, Косинус, который отличается от 0).

Итак, приблизительное значение Python для numpy.power(complex(-1), .5) в конечном счете из-за ограничения чисел с плавающей запятой, и вероятно, можно найти на многих языках.

то, что вы наблюдаете, связано с этим ограничением с плавающей запятой через реализацию мощности числа. В вашем примере квадратный корень вычисляется путем вычисления модуля и аргумента вашего комплексного числа(по существу, через функцию log, которая возвращает log (module) + I phase). С другой стороны,--2--> дает именно 1j потому что он использует другой метод и не страдает от плавающей точки задача аппроксимации (-1+0j)**0.5 (как полагают TonyK).


попробуйте numpy.real_if_close().

посмотреть: реально, если закрыть