Python 的 sympy 求解器在 4 次方程上返回坏根
Python's sympy solver returning bad roots on 4th degree equation
我需要用 python 求解四次方程。为此,我使用 sympy 模块。
当我 运行 脚本时,sympy return 将方程的 4 个解作为复数(见输出),而实际上,都是真实的。
为什么 sympy return 的答案是错误的?
import numpy as np
import math
from numpy import linalg as la
import sympy as sy
from matplotlib.pyplot import *
L = np.array([0,1,-20.0])
S = np.array([0,0,-10.0])
a = np.dot(S,S)
b = np.dot(S,L)
c = np.dot(L,L)
k0 = a - 1
k1 = 2*(a-b)
k2 = a + 2*b + c - 4*a*c
k3 = -4*(a*c - b**2)
k4 = 4*c*(a*c - b**2)
y = sy.Symbol('y')
r = sy.solvers.solve(k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0, y)
print r
y = np.linspace(-1.1, 1.1, 1000)
x = k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0
figure()
plot(y, x)
grid(True)
show()
输出:
[-0.994999960838935 + 1.66799419488535e-31*I,
-0.0255580200028216 - 6.34301512012529e-30*I,
0.0243009597954184 + 6.32628752256216e-30*I,
0.998750786632373 - 1.50071821925406e-31*I]
剧情(有4个zero-crossings):
请注意,结果实际上是真实的,达到数值精度。 e-30
真是个小数目。解说也和剧情一致,不用担心
也可以直接从nroots
:
获取真实值
>>> eq=k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0
>>> eq
160400.0*y**4 - 400.0*y**3 - 159499.0*y**2 - 200.0*y + 99.0
>>> nroots(eq)
[-0.994999960838935, -0.0255580200028216, 0.0243009597954184, 0.998750786632373]
我需要用 python 求解四次方程。为此,我使用 sympy 模块。
当我 运行 脚本时,sympy return 将方程的 4 个解作为复数(见输出),而实际上,都是真实的。
为什么 sympy return 的答案是错误的?
import numpy as np
import math
from numpy import linalg as la
import sympy as sy
from matplotlib.pyplot import *
L = np.array([0,1,-20.0])
S = np.array([0,0,-10.0])
a = np.dot(S,S)
b = np.dot(S,L)
c = np.dot(L,L)
k0 = a - 1
k1 = 2*(a-b)
k2 = a + 2*b + c - 4*a*c
k3 = -4*(a*c - b**2)
k4 = 4*c*(a*c - b**2)
y = sy.Symbol('y')
r = sy.solvers.solve(k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0, y)
print r
y = np.linspace(-1.1, 1.1, 1000)
x = k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0
figure()
plot(y, x)
grid(True)
show()
输出:
[-0.994999960838935 + 1.66799419488535e-31*I,
-0.0255580200028216 - 6.34301512012529e-30*I,
0.0243009597954184 + 6.32628752256216e-30*I,
0.998750786632373 - 1.50071821925406e-31*I]
剧情(有4个zero-crossings):
请注意,结果实际上是真实的,达到数值精度。 e-30
真是个小数目。解说也和剧情一致,不用担心
也可以直接从nroots
:
>>> eq=k4*y**4 + k3*y**3 + k2*y**2 + k1*y + k0
>>> eq
160400.0*y**4 - 400.0*y**3 - 159499.0*y**2 - 200.0*y + 99.0
>>> nroots(eq)
[-0.994999960838935, -0.0255580200028216, 0.0243009597954184, 0.998750786632373]