我的durand-kerner实施有什么问题?

时间:2013-11-10 06:28:42

标签: c++

实现这种简单的根查找算法。 http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method 我不能为我的生活弄清楚我的实施有什么问题。根部不断爆炸,没有收敛的迹象。有什么建议吗?

感谢。

#include <iostream>
#include <complex>

using namespace std;

typedef complex<double> dcmplx;

dcmplx f(dcmplx x)
{
    // the function we are interested in
    double a4 = 3;
    double a3 = -3;
    double a2 = 1;
    double a1 = 0;
    double a0 = 100;

    return a4 * pow(x,4) + a3 * pow(x,3) + a2 * pow(x,2) + a1 * x + a0;
}


int main()
{   

dcmplx p(.9,2);
dcmplx q(.1, .5);
dcmplx r(.7,1);
dcmplx s(.3, .5);

dcmplx p0, q0, r0, s0;

int max_iterations = 20;
bool done = false;
int i=0;

while (i<max_iterations && done == false)
{   
    p0 = p;
    q0 = q;
    r0 = r;
    s0 = s;


p = p0 - f(p0)/((p0-q0)*(p0-r0)*(p0-s0));
q = q0 - f(q0)/((q0-p)*(q0-r0)*(q0-s0));
r = r0 - f(r0)/((r0-p)*(r0-q)*(r0-s0));
s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));

    // if convergence within small epsilon, declare done
    if (abs(p-p0)<1e-5 && abs(q-q0)<1e-5 && abs(r-r0)<1e-5 && abs(s-s0)<1e-5)
        done = true;

    i++;
}

cout<<"roots are :\n";
cout << p << "\n";
cout << q << "\n";
cout << r << "\n";
cout << s << "\n";
cout << "number steps taken: "<< i << endl;

return 0;
}

3 个答案:

答案 0 :(得分:1)

啊,问题是N度多项式的系数必须指定为

1 * x ^ N + a * x ^(N-1)+ b * x ^(N-2)...... etc + z;

其中1是最大学位词的系数。否则第一个根将永远不会收敛。

答案 1 :(得分:1)

迟到半年:谜的解决方案是分母应该是多项式导数的近似值,因此需要包含前导系数a4作为因子。

或者,可以在return语句中将多项式值除以a4,以便多项式有效地进行标准化,即具有超前系数1.

请注意,Bo Jacoby在维基百科中的示例代码是该方法的Seidel型变体,经典公式是类似Jordan的方法,其中所有新近似都是从旧近似计算的。 Seidel可以比作为多维牛顿方法的公式为Jacobi提供的2阶的收敛速度更快。

然而,对于较大的度数,Jacobi可以使用快速多项式乘法算法加速,以进行多项式值和分母中的乘积所需的多点评估。

答案 2 :(得分:0)

您尚未正确实施公式。例如

s = s0 - f(s0)/((s0-p0)*(s0-q0)*(s0-r0));

应该是

s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));

再看一下维基文章