如何使用牛顿方法查找多项式的所有根,而不仅仅是唯一的?
作为一个例子,我有这个等式:x^2-12x+34=0
,当我使用这个公式时,我只得到一个根4.5857
,我怎样才能获得第二个根 - 7.4142
?
答案 0 :(得分:2)
从不同的起始位置重新启动Newton Raphson。
我在这里粘贴了一些我在开发金融工具定价库时实施的代码。在这里看到我的代码为Newton Raphson。您将输入参数视为起始位置double start
之一。您可以从网格上的不同位置开始,例如并将解决方案与您已经找到的解决方案进行比较。
#include "math.h"
#include "ExceptionClass.h"
template <class T, double (T::*Value)(const double) const,
double (T::*Derivative)(const double) const>
double NewtonRaphson(double Target, double start, double Tolerance,
size_t max_count, const T& Object)
{
size_t count = 0;
double diff = Target-(Object.*Value)(start);
double x = start;
double derivative = (Object.*Derivative)(start);
do{
count++;
if(fabs(derivative) < 1.E-6)
throw DivideByZeroException("Dividing by a derivative smaller than: 1.E-6!");
x = x - diff/(-derivative);
diff = Target-(Object.*Value)(x);
derivative = (Object.*Derivative)(x);
} while((fabs(diff)>Tolerance)&&(count < max_count));
if(count >= max_count)
throw("Newton-Raphson did not converge in the defined number of steps!");
else return x;
}
T是一个类,您可以在其中定义函数来计算(二次)方程(此处由模板中的double (T::*Value)(const double) const
引用)和此方程的导数(此处由double (T::*Derivative)(const double) const
引用)模板)。
注意我已经包含了一个异常类,因为Newton Raphson有一些问题。
使用二分算法获得更稳定的算法。
实际上,您可以使用小于1.E-6
的数字。
值应该是指向评估二次函数的函数的指针,目标应设置为0,导数应该是指向函数导数的指针。
在您的情况下,我的模板代码可以简化:
将代码diff = Target-(Object.*Value)(x);
替换为diff = (Object.*Value)(x);
将x = x - diff/(-derivative);
替换为x = x - diff/(derivative);
此代码将更容易被识别为Newton Raphson算法。
如果你想提高收敛速度,可以使用Halley(是彗星中的人)算法或Householder算法。
请参阅c ++中的数字配方以了解替代实现。 C ++中的数字配方是解决这类问题的书。