我已经实现了用于在C中查找根的牛顿raphson算法。我想尽可能打印出最精确的根的近似,而不是进入南地。我的策略是while (!(isnan(x0)) { dostuff(); }
但是这会继续多次打印出结果。理想情况下,我想设置一个范围,以便在前一个电流小于某个范围.000001的情况下,每个计算的x截距近似值之间的差异将停止。我有一个可能的实现如下。当我输入2.999只需要一步,但是当我输入3.0时需要20步,这对我来说似乎不对。
(当我输入3.0时)
λ newton_raphson 3 2.500000 2.250000 2.125000 2.062500 2.031250 2.015625 2.007812 2.003906 2.001953 2.000977 2.000488 2.000244 2.000122 2.000061 2.000031 2.000015 2.000008 2.000004 2.000002 2.000001 Took 20 operation(s) to approximate a proper root of 2.000002 within a range of 0.000001
(当我输入2.999时)
λ newton_raphson 2.999 Took 1 operation(s) to approximate a proper root of 2.000000 within a range of 0.000001
我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define RANGE 0.000001
double absolute(double number)
{
if (number < 0) return -number;
else return number;
}
double newton_raphson(double (*func)(double), double (*derivative)(double), double x0){
int count;
double temp;
count = 0;
while (!isnan(x0)) {
temp = x0;
x0 = (x0 - (func(x0)/derivative(x0)));
if (!isnan(x0))
printf("%f\n", x0);
count++;
if (absolute(temp - x0) < RANGE && count > 1)
break;
}
printf("Took %d operation(s) to approximate a proper root of %6f\nwithin a range of 0.000001\n", count, temp);
return x0;
}
/* (x-2)^2 */
double func(double x){ return pow(x-2.0, 2.0); }
/* 2x-4 */
double derivative(double x){ return 2.0*x - 4.0; }
int main(int argc, char ** argv)
{
double x0 = atof(argv[1]);
double (*funcPtr)(double) = &func; /* this is a user defined function */
double (*derivativePtr)(double) = &derivative; /* this is the derivative of that function */
double result = newton_raphson(funcPtr, derivativePtr, x0);
return 0;
}
答案 0 :(得分:2)
您致电trunc(x0)
,将2.999
变为2.0
。当然,当你从正确答案开始时,不需要迭代!换句话说,虽然您打算使用2.999
作为起始值,但实际上使用了2.0
。
只需移除对trunc()
的调用。
答案 1 :(得分:1)
值得指出:采取20步收敛是也异常;因为你正在收敛到一个多根,所以收敛只是线性的,而不是Newton-Raphson在一般情况下给出的典型二次收敛。你可以看到这一点,你的错误在每次迭代时减半(通常的二次收敛,你会得到每次迭代的正确数字的两倍,收敛得更快,更快)。