Python 多项式根不准确

标签 python numpy sympy polynomials

我试图实现的算法需要找到我用 sympy 创建的 10 次多项式的根,它看起来像这样:

import sympy
import numpy as np
det = sympy.Poly(1.3339507303385e-16*z**10 + 6.75390067076469e-14*z**9 + 7.18791227134351e-12*z**8 + 2.27504286959352e-10*z**7 + 2.37058998324426e-8*z**6 + 1.63916629439745e-6*z**5 + 3.0608041245671e-5*z**4 + 4.83564348562906e-8*z**3 + 2.0248073519853e-5*z**2 - 4.73126177166988e-7*z + 1.1495883206077e-6)

为了求多项式的根,我使用以下代码:

coefflist = det.coeffs()
solutions = np.roots(coefflist)
print(coefflist)
[1.33395073033850e-16, 6.75390067076469e-14, 7.18791227134351e-12, 2.27504286959352e-10, 2.37058998324426e-8, 1.63916629439745e-6, 3.06080412456710e-5, 4.83564348562906e-8, 2.02480735198530e-5, -4.73126177166988e-7, 1.14958832060770e-6]

print(solutions)
[-3.70378229e+02+0.00000000e+00j -1.18366138e+02+0.00000000e+00j
  2.71097137e+01+5.77011644e+01j  2.71097137e+01-5.77011644e+01j
 -3.59084863e+01+1.44819591e-02j -3.59084863e+01-1.44819591e-02j
  2.60969082e-03+7.73805425e-01j  2.60969082e-03-7.73805425e-01j
  1.42936329e-02+2.49877948e-01j  1.42936329e-02-2.49877948e-01j]

但是,当我用根替换 z 时,比如说第一个,结果不是零,而是某个数字:

print(det.subs(z,solutions[0]))
-1.80384169514123e-6

我本以为结果可能不是整数 0,但 1e-6 非常糟糕(它应该为零,对吧?)。我的代码有错误吗?这种不准确是正常的吗?任何想法/建议都会有帮助。是否有更准确的替代方法来计算 10 次多项式的根?

最佳答案

你不需要sympy,numpy中的方法完全足够了。通过系数列表定义多项式并计算根

p=[1.33395073033850e-16, 6.75390067076469e-14, 7.18791227134351e-12, 2.27504286959352e-10, 2.37058998324426e-8, 1.63916629439745e-6, 3.06080412456710e-5, 4.83564348562906e-8, 2.02480735198530e-5, -4.73126177166988e-7, 1.14958832060770e-6]
sol= np.roots(p); sol

给出结果

array([ -3.70378229e+02 +0.00000000e+00j,  -1.18366138e+02 +0.00000000e+00j,
         2.71097137e+01 +5.77011644e+01j,   2.71097137e+01 -5.77011644e+01j,
        -3.59084863e+01 +1.44819592e-02j,  -3.59084863e+01 -1.44819592e-02j,
         2.60969082e-03 +7.73805425e-01j,   2.60969082e-03 -7.73805425e-01j,
         1.42936329e-02 +2.49877948e-01j,   1.42936329e-02 -2.49877948e-01j])

并评估这些近似根处的多项式

np.polyval(p,sol)

给出数组

array([  2.28604877e-06 +0.00000000e+00j,   1.30435230e-10 +0.00000000e+00j,
         1.05461854e-11 -7.56043461e-12j,   1.05461854e-11 +7.56043461e-12j,
        -3.98439686e-14 +6.84489332e-17j,  -3.98439686e-14 -6.84489332e-17j,
         1.18584613e-20 +1.59976730e-21j,   1.18584613e-20 -1.59976730e-21j,
         6.35274710e-22 +1.74700545e-21j,   6.35274710e-22 -1.74700545e-21j])

显然,计算接近根的多项式会涉及大量灾难性的抵消,即中间项的符号相反且抵消,但它们的误差与其原始大小成正比。要估计组合误差大小,请将多项式系数替换为其绝对值以及评估点。

np.polyval(np.abs(p),np.abs(sol))

结果

array([  1.81750423e+10,   8.40363409e+05,   
         8.08166359e+03,   8.08166359e+03,
         2.44160616e+02,   2.44160616e+02,
         2.50963696e-05,   2.50963696e-05,
         2.65889696e-06,   2.65889696e-06])

在第一个根的情况下,标度乘以机器常数得出的误差标度为1e+10*1e-16=1e-6,这意味着根处的值在 double 浮点框架内与零一样好。

关于Python 多项式根不准确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58651514/

相关文章:

python - Matplotlib 图表 X 轴上的更改顺序

python - 使用 Python 对 PDF 文档进行数字签名

python - 如何过滤一个 Numpy 数组,使每个 X 值只有一个 Y 值

python - 关于 numpy 数组在 Python 中如何存储的一些困惑

python-3.x - 从由 reduce_rational_inequalities([[-3 < 2*x + 1]], x) 给出的 And 对象中提取值。示例.And(-2 < x, x < oo)

python - 如何在 scipy 中创建数学表达式?

python - 在 Qt 中启动单独的进程

python - 用日期时间索引组成数据框

python - PyCharm 中的 Numpy 导入错误(导入多数组 numpy 扩展模块失败)

python - SymPy逻辑函数的同步替换