题目:用牛顿迭代法求方程2x³-4x²+3x-6=0在1.5附近的根。
求解原理:
令f(x)=2x³-4x²+3x-6,f´(x)为导数,f´(x)=6x²-8x+3
令xn=1.5,迭代求得的xn+1=xn-f(xn)/f´(xn),如果f(xn+1)=0,算法结束。
思路1:宏定义函数和do-while循环
#include <stdio.h>
#include <math.h>
#define f(x) (2*(x)*(x)*(x) - 4*(x)*(x) + 3*(x) - 6)
#define fd(x) (6*(x)*(x) - 8*(x) + 3)
double n(double x0);
int main(void)
{
double x0 = 1.5, root;
root = n(x0);
printf("方程的根为: %f\n", root);
return 0;
}
double n(double x0)
{
double x1, f0, fd0;
do
{
f0 = f(x0);
fd0 = fd(x0);
x1 = x0 - f0 / fd0;
x0 = x1;
}
while (fabs(f0) > 1e-6);
return x1;
}
思路2:直接定义函数和for循环
#include <stdio.h>
#include <math.h>
double f(double x)
{
return 2 * pow(x, 3) - 4 * pow(x, 2) + 3 * x - 6;
}
double f_p(double x)
{
return 6 * pow(x, 2) - 8 * x + 3;
}
int main(void)
{
double x = 1.5, x_d, e = 1e-6;
int i;
for (i = 0; i < 100; i++)
{
x_d = x - f(x) / f_p(x);
if (fabs(x_d - x) < e)
{
break;
}
x = x_d;
}
if (i < 100)
{
printf("方程的根为%lf\n", x_d);
} else
{
printf("没有找到根\n");
}
return 0;
}
比较来看,do-while循环更直观,也更能反映出牛顿迭代的过程。但第二个代码设置了一个最大迭代次数的限制,而第一个没有。那么如果第一个代码无法收敛,它就会产生无限循环,而第二个代码会在一定次数后停止迭代,防止程序进入死循环。此外直接定义函数也更加清晰,更加方便调试。因此综合来看第二个代码似乎更佳。