2012年(106)
分类: C/C++
2012-05-08 01:35:50
求解方程:f(x)=0的解 f(x)=3x^4-5x^3+4x-11 迭代多少次
练习:求解方程:f(x)=0的解f(x)=3x^4-5x^3+4x-11 迭代多少次
程序如下:
1.迭代法(不动点法):(利用公式:Sn-1=Sn-f(Sn)/f’(Sn) (n=0,1,^) )
/*算法描述:
用迭代法求下面方程
y=x(x*x(3*x-5)+3)-11的实根的过程是:
1.想在谁附近求解,这个范围或者这个数值大多是题目已经给定了的(本程序是根据输入的数值来计算的)
2.令f(x)=x(x*x(3*x-5)+3)-11
3.x1=X
4.求f(x1)
5.对f(x)求导,得到f1(x),求f1(x1)
6.调整x,使x=x1-f(x1)/f1(x1)
7.符合条件x-x1>1e-6,转到第3步
8.不符合条件x-x1>1e-6,则x1就是要求的实根
*/
#include
#include
//y=x(x*x(3*x-5)+3)-11
float f(float x)
{
return (3*pow(x,4)-5*pow(x,3)+4*x-11);
}
float f1(float x)
{
return (12*pow(x,3)-15*pow(x,2)+3);
}
void main()
{
float x,x1,y1,y2;
int n=0;
printf("请输入一个任意实数:X=");
scanf("%f",&x);
printf("这个方程的近似解\n");
do
{
x1=x;
y1=f(x);
y2=f1(x1);
x=x1-y1/y2;
n++;
}
while (fabs(x-x1)>=1e-6);
printf("A root is %f\n",x1);
printf("迭代次数:%d\n",n);
}
未解决问题:
无法求出全部的解,只能根据猜想的范围来进行取值,如此题我就是取了四个值,分别是正数、负数、0和特殊值,然后得到了2个解。但如果是更加复杂的方程,x的次数很高,我不知道如何才能找到准确的全部解。另外,在我取值1时,出现了1.#INF00的结果。我发现这是由于当X取1时,f1(x)=0,这样就使得除数为0,所以产生了这样的结果,但改写程序后依然错误。还需要再思考下!
改写:
#include
#include
//y=x(x*x(3*x-5)+3)-11
float f(float x)
{
return (3*pow(x,4)-5*pow(x,3)+4*x-11);
}
float f1(float x)
{
float t,s;
t=12*pow(x,3)-15*pow(x,2)+3;
if(t==0)
{printf("ERROR,INPUT AGAIN: ");
scanf("%f",&s);
float f1(s);}
else return t;
}
void main()
{
float x,x1,y1,y2;
int n=0;
printf("请输入一个任意实数:X=");
scanf("%f",&x);
printf("这个方程的近似解\n");
do
{
x1=x;
y2=f1(x1);
y1=f(x);
x=x1-y1/y2;
n++;
}
while (fabs(x-x1)>=1e-6);
printf("A root is %f\n",x1);
printf("迭代次数:%d\n",n);
}
2.二分法:
#include
#include
double f(double x)
{
return 3*x*x*x*x-5*x*x*x+4*x-11;
}
main()
{
int n=0;
double left=-10,right=10,mid;
double ans;
do
{
mid=(left+right)/2;
ans=f(mid);
if(ans>0)
right=mid;
else if(ans<0)
left=mid;
else
break;
n++;
}while(right-left>1e-6);
printf("近似结果:%lf\t%lf\n",mid,ans);
printf("迭代次数:%d\n",n);
}
3.弦截法:
//弦截法求3*x*x*x*x-5*x*x*x+4*x-11=0的根
#include
#include
float f(float x)
{ //计算f(x)的值
return 3*x*x*x*x-5*x*x*x+4*x-11;
}
float point(float x1 ,float x2)
{
//计算与x轴交点的x值
return (x1*f(x2)-x2*f(x1))/(f(x2)-f(x1));
}
void main()
{
int n=0;
//输入两个数x1,x2
float x1,x2,x;
do
{
printf("输入两个数x1,x2:");
scanf("%f%f",&x1,&x2);
}
while (f(x1)*f(x2) >= 0); //当输入两个数大于0为真时,继续重新输入
//关键循环步骤:
do
{
x=point(x1,x2);//得到交点的值
if(f(x)*f(x1)>0)
x1=x; //新的x1
else
x2=x;
n++;
}
while (fabs(f(x)) > 0.000001); //0.000001为取值精度
printf("一个解为%f\n",x);
printf("迭代次数:%d\n",n);
}
经过三种方法的结果对比可知:二分法不能计算复根和重根,不动点法可以用来求方程的重根、复根,单纯的从算法说,不动点法循环的次数比二分法少,并且误差也比较小。弦截法比二分法收敛得快。效率:二分法<弦截法<不动点法