求解方程:x3-0.2x2-0.2x-1.2=0的根
编写二分法、牛顿法程序,分析运行结果。
思想:
二分法
给定区间,并设f(a)与f(b)符号相反,取Ɛ1为根的允许误差,Ɛ2为|f(x)|的允许误差。
1)c=(a+b)/ 2;
2)如果(c-a)< Ɛ1或|f( c )|< Ɛ2,则输出 c,结束;否则执行3);
3)如果 f( a )·f( b ) > 0,则令 a=c,否则令 b=c,重复以上步骤。
牛顿迭代法
给定初值x0,取Ɛ1为根的允许误差,Ɛ2为|f(x)|的允许误差,N为迭代次数的允许值。
1)如果 f’(x0)=0 或迭代次数大于N,则算法失败,结束,否则执行2);
2)计算 x1 = x0 - (f(x0) / f’(x0));
3)若|x1 - x0|< Ɛ1或|f(x1)|< Ɛ2,则输出x1,程序结束,否则执行4);
4)令 x0 = x1,转向1)。
代码:
//二分法
#include <stdio.h>
#include <math.h>
float Bisection(float a, float b, float (*f)(float)) {
float c,fa=(*f)(a),fb=(*f)(b),fc=(*f)(c);
int n=1;
printf("二分次数 \t c \t f(c)\n");
while(1){
if(fa * fb > 0){
printf("不能用二分法求解!");
break;
}
c = ( a + b ) / 2;
printf("%d \t %f \t %f\n",n++,c,fc);
if(fabs(fc) < 1e-6)
break;
else if(fa * fc < 0){
b = c;
fb = fc;
}
else{
a=c;
fa=fc;
}
if (b-a < 5e-6)
break;
}
return c;
}
float f(float x){
return pow(x,3)-0.2*pow(x,2)-0.2*x-1.2; //方程
}
int main(int argc, char* argv[]){
float a=1,b=2; //注意有根区间的判断
float x;
x = Bisection(a,b,f);
printf("\n方程的根为:%f",x);
return 0;
}
//牛顿迭代法
#include <stdio.h>
#include <math.h>
float Newton(float(*f)(float), float(*f1)(float), float x0){
float x1,d;
int k=0;
do{
x1 = x0 - (*f)(x0) / (*f1)(x0);
if(k++>100 || fabs((*f1)(x1)) < 1e-6){
printf("\nNewton迭代法发散!");
break;
}
d = fabs(x1) <1 ? x1-x0 : (x1-x0)/x1;
x0 = x1;
printf("x(%d) = %f\t",k,x0);
}
while(fabs(d)>1e-6 && fabs((*f)(x1)) > 1e-8);
return x1;
}
float f(float x){
return pow(x,3)-0.2*pow(x,2)-0.2*x-1.2; //方程
}
float f1(float x){
return 3.0*pow(x,2)-0.4*x-0.2; //方程求导
}
int main(){
float x0,y0;
printf("请输入迭代初值x0\n:");
scanf("%f",&x0);
printf("x(0) = %f\n",x0);
y0 = Newton(f,f1,x0);
printf("方程的根为:%f\n",y0);
}
运行结果:
分析:
1、无论选哪种方法,首先都要进行有根区间的判断。
2、牛顿迭代法取不同初值得到同样的结果,但迭代次数不同。初值越接近所求的根,迭代次数越少。所以在取初值时,可以先采用二分法取得一个好的初值,再进行迭代。