有人会期望并希望如果你要求Mathematica
找到多项式的根,它应该给出相同的(近似的)答案,无论你是否象征性地这样做,然后找到这些精确答案的数值近似值,或者你是否用数字做。这是一个示例(在{X}中运行的Mathematica 7
),这会导致严重失败:
poly = -112 + 1/q^28 + 1/q^26 - 1/q^24 - 6/q^22 - 14/q^20 - 25/q^18 -
38/q^16 - 52/q^14 - 67/q^12 - 81/q^10 - 93/q^8 - 102/q^6 - 108/
q^4 - 111/q^2 - 111 q^2 - 108 q^4 - 102 q^6 - 93 q^8 - 81 q^10 -
67 q^12 - 52 q^14 - 38 q^16 - 25 q^18 - 14 q^20 - 6 q^22 - q^24 +
q^26 + q^28;
Total[q^4 /. NSolve[poly == 0, q]] - Total[q^4 /. N[Solve[poly == 0, q]]]
(注意:这实际上是一个Laurent多项式,如果你乘以q
的大功率,问题就会消失。)
这里的最后一行只是证明所找到的解决方案非常不同;事实上,这是我们在努力解决的问题中试图计算的数量。
如果仔细查看NSolve[poly == 0, q]
和N[Solve[poly == 0, q]
的输出,您会发现NSolve只提供54
个根而不是预期的56
。并不只是错过了重复的根或任何东西;它缺少两个最大的根(大约+/- 1.59
)
这是Mathematica中的错误吗?有没有人解释为什么会这样?
答案 0 :(得分:7)
不幸的是,你的期望是没有根据的。
正如您所说,Solve[]
提供了一个精确的解决方案,N[]
引入了一个小错误,但只有一次,当您评估它时。另一方面,NSolve[]
使用来自get get的数值近似值,因此可以累积显着的舍入误差。
您还受到计算的默认精度的限制,这可能导致数值方法完全失败,例如缺少根(请参阅Wilkinson's polynomial)。您可以通过告诉NSolve[]
使用更高的精度来抵消这一点:
In[1] := Total[q^4 /. NSolve[poly == 0, q, WorkingPrecision -> 50]] -
Total[q^4 /. N[Solve[poly == 0, q]]]
Out[1] := 0. - 3.66374*10^-15 I
使用数值方法时,记住错误始终很重要。因为对于从解决长多项式到对角化大矩阵到奇怪函数等的整合等各种numerical analysis问题都是如此。没有一种正确的方法,并且Mathematica需要被告知,例如,提高WorkingPrecision,或应用不同的数值技术。