的立方根为了提高三次方程np.roots
的表现,我尝试实施Cardan(o) Method:未能实施Cardano方法。复数
def cardan(a,b,c,d):
#"resolve P=ax^3+bx^2+cx+d=0"
#"x=z-b/a/3=z-z0 => P=z^3+pz+q"
z0=b/3/a
a2,b2 = a*a,b*b
p=-b2/3/a2 +c/a
q=(b/27*(2*b2/a2-9*c/a)+d)/a
D=-4*p*p*p-27*q*q+0j
r=sqrt(-D/27)
J=-0.5+0.86602540378443871j # exp(2i*pi/3)
u=((-q+r)/2)**(1/3)
v=((-q-r)/2)**(1/3)
return u+v-z0,u*J+v/J-z0,u/J+v*J-z0
它运作良好时,根实:
In [2]: P=poly1d([1,2,3],True)
In [3]: roots(P)
Out[3]: array([ 3., 2., 1.])
In [4]: cardan(*P)
Out[4]: ((3+0j), (1+0j), (2+1.110e-16j))
但在失败复杂的情况:
In [8]: P=poly1d([1,-1j,1j],True)
In [9]: P
Out[9]: poly1d([ 1., -1., 1., -1.])
In [10]: roots(P)
Out[10]: array([ 1.0000e+00+0.j, 7.771e-16+1.j, 7.771e-16-1.j])
In [11]: cardan(*P)
Out[11]: ((1.366+0.211j),(5.551e-17+0.577j),(-0.366-0.788j))
我想这个问题是u
的评价d v
由立方根。 Theory说uv=-p/3
,但这里uv=pJ/3
:(u,v)
是不是一个好根。
什么是在所有情况下获得正确配对的最佳方法?
编辑
@Sally文章后,我可以准确的问题。好的一对并不总是(u,v)
,它可以是(u,vJ)
或(uJ,v)
。所以问题可能是:
- 是否有一个简单的方法来捕捉好对?
而终极:目前,通过编写此代码与Numba
,它比np.roots
快20倍。
- 有没有更好的算法来计算三次方程的三个根?
你在寻找类似De Moivre定理的东西吗? – AMACB
不是真的。 'sin'和'cos'很耗时。我看着一个快速的方法来知道'(v,Jv,J?v)'必须与'u'相关联以找到好的根。 –
他们不应该是,除非你使用他们*很多*:http://stackoverflow.com/a/3836083/5277935 – AMACB