Numpy - -1的平方根留下一个小的实部

cra*_*sic 13 python floating-point numpy square-root

也许这是一个算法问题,但是下面的一段代码

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

产生以下输出

(6.1230317691118863e-17+1j)

numpy.power(complex(-1),.5)然而,类似的表达式产生相同的结果 - numpy.sqrt(complex(-1))产生预期的结果1j.显然,结果应该没有真正的部分,所以我遗漏了一些关键的东西,或者我需要向numpy dev's报告.

如果有人问,不,我不能完全摆脱真实部分(我需要完全精确的计算),是的,我需要使用电源功能.

Eri*_*got 15

发生的是-1的平方根计算为exp(i phase/2),其中相位(-1)约为 π.事实上,

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

这表明-1的相位是π,只有几个1e-17; 相位除以2也只是大约π/ 2,其余弦只有大约0,因此你的结果(你的结果的真实部分是这个余弦).

问题最终来自于只存在固定的有限数量的浮点数.数字π不在浮点数列表中,因此只能近似表示.π/ 2也不能精确表示,因此-1的平方根的实部是浮点近似π/ 2的余弦(因此余弦不等于0).

因此,Python的近似值numpy.power(complex(-1), .5)最终归因于浮点数的限制,并且很可能在许多语言中找到.

您观察到的是通过实现数字的幂来连接到这个浮点限制.在您的示例中,通过计算模块和复数的参数(主要通过log函数,返回log(模块)+ i阶段)来计算平方根.另一方面,cmath.sqrt(-1)完全是1j因为它使用了不同的方法,并且没有遭受(-1+0j)**0.5(如TonyK所建议的)浮点近似问题.


Ign*_*ams 9

这是numpy.power()复杂数字实现的副作用.stdlib表现出同样的问题.

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

  • 通常,复杂的"power"函数必须评估(实际)对数和三角函数.但是`sqrt`函数只需要求解几个二次方程.因此,一个好的实现将提供一个自定义的`sqrt`函数,它比`power`更快,更准确. (14认同)

小智 5

试试numpy.real_if_close().

请参阅:真实,如果关闭