【发布时间】:2014-12-14 12:39:55
【问题描述】:
我被要求找到 f(x) = 5x(e^-mod(x))cos(x) + 1 的根。我之前使用过 Durand-Kerner 方法来查找函数 x^4 -3x^3 + x^2 + x + 1 的根,代码如下所示。我以为我可以简单地重用代码来查找 f(x) 的根,但是每当我用 f(x) 替换 x^4 -3x^3 + x^2 + x + 1 时,程序都会为所有根输出 nan。我的 Durand-Kerner 实现有什么问题,我该如何修改它以适用于 f(x)?如果有任何帮助,我将不胜感激。
#include <iostream>
#include <complex>
#include <math.h>
using namespace std;
typedef complex<double> dcmplx;
dcmplx f(dcmplx x)
{
// the function we are interested in
double a4 = 1;
double a3 = -3;
double a2 = 1;
double a1 = 1;
double a0 = 1;
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 = 100;
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-q)*(p0-r)*(p0-s));
q = q0 - f(q0)/((q0-p)*(q0-r)*(q0-s));
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;
}
到目前为止,我唯一更改的是 dcmplx f 函数。我一直把它改成
dcmplx f(dcmplx x)
{
// the function we are interested in
double a4 = 5;
double a0 = 1;
return (a4 * x * exp(-x) * cos(x) )+ a0;
}
【问题讨论】:
标签: c++ polynomial-math nonlinear-functions newtons-method