1. 二分法求方程的根

二分法可行的条件是有介值定理支持。

介值定理说明在实数范围内,区间上可以画出一个连续曲线。 存在,那么存在, ,使得

二分法就是异号时,介值定理的特殊情况,即存在实数使得存在。

#include"math.h"
#include"stdio.h"
#include"stdlib.h"
double fun(double k)
{return 1-k-sin(k);//所求方程 
}
void main()
{double a,b,x;int i=0;
printf("No.0004二分法求方程的根\n\n输入区间左端点:");
scanf("%lf",&a);
printf("输入区间右端点:"); 
scanf("%lf",&b);
x=(a+b)/2.0;
while(/*fabs(fun(x))>0.00005||*/fabs(a-b)>0.00005)//近似范围 
{
if(fun(a)*fun(x)<0) b=x;
if(fun(b)*fun(x)<0) a=x;
x=(a+b)/2.0;
i++;}
printf("方程的根:%lf\n",x);
printf("迭代次数:%d\n\n",i);
system("pause");
}

2. 迭代法求方程的根

迭代法主要是将这种等式,该写成,然后给定一个初始的,根据公式,求出,接下来,比较的差值大小,如果差值等于0或者一个非常非常小的数,那么则求出最终的即为;如果差值还很大,则进行迭代步骤,将带入到公式右侧,求出左侧的,重复上述比较步骤,直到收敛于一个定值。

#include"math.h"
#include"stdio.h"
#include"stdlib.h"
double fun(double k)
{
	return pow(1+k*k,1/3.0);//所求方程 
}
void main()
{double a,b,x,x1,l=1;
int i=0,p;
printf("No.0005迭代法方程的根\n\n选择输入数据种类:\n1.数值\n2.区间\n");
printf("\n");
while(l==1)
{scanf("%d",&p);
if(p!=1&&p!=2) printf("请输入指定序号\n\n");//判断输入的序号是否正确 
else l=0;
}
switch(p)
 {
 case 1:
		printf("数据种类\n1.数值\n输入数值:");
		scanf("%lf",&x);
		x1=fun(x);i=i+1;
		break;
 case 2:printf("数据种类\n2.区间\n");
		printf("输入区间左端点:");
		scanf("%lf",&x);
		printf("输入区间右端点:");
		scanf("%lf",&x1);x1=fun((x+x1)/2.);i=i+1;
		break;
 }
while(fabs(x-x1)>0.00005)
{
x=fun(x1);
i=i+1;
x1=fun(x);
i=i+1;
}
printf("方程的根:%lf\n",x1); 
printf("迭代次数:%d\n\n",i);
system("pause");
}

3.牛顿迭代法

牛顿迭代法又称为牛顿-拉弗森方法(Newton-Raphson method),它比一般的迭代法有更高的收敛速度。

Newton-Raphson method

点的切线是的线性逼近。离点距离越近,这种逼近的效果也就越好,也就是说,切线与曲线之间的误差越小。所以我们可以说在点附近,

牛顿-拉弗森方法提出来的思路就是利用切线是曲线的线性逼近这个思想,随便找一个曲线上的点(为什么随便找,根据切线是切点附近的曲线的近似,应该在根点附近找,但是很显然我们现在还不知道根点在哪里),做一个切线,切线的根(就是和x轴的交点)与曲线的根,还有一定的距离。我们从这个切线的根出发,做一根垂线,和曲线相交于点,继续重复刚才的工作,多次迭代后会越来越接近曲线的根,即迭代收敛。

在计算时,首先选择一个,然后计算相应的和切线斜率,接下来计算穿过点(,)并且斜率为的直线和轴的交点的坐标,公式为: , 将其转化为的形式,即有:

将初始的代入到上述公式中,经过多次迭代,可以求得最后的根。

#include"math.h"
#include"stdio.h"
#include"stdlib.h"
double fun(double k)
{
	return k*k*k-k*k-1;//所求方程 
}
double fun1(double k)
{  
	return 3*k*k-2*k;//所求方程的一阶导函数 
}
void main()
{double a,b,x,x1,l=1;
int i=0,p;
printf("No.0006牛顿迭代法求方程的根\n\n选择输入数据种类:\n1.数值\n2.区间\n");
printf("\n");
while(l==1)
{scanf("%d",&p);
if(p!=1&&p!=2) printf("请输入指定序号\n\n");//判断输入的序号是否正确 
else l=0;
}
switch(p)
{
 case 1:
		printf("数据种类\n1.数值\n输入数值:");
		scanf("%lf",&x1);
		break;
 case 2:printf("数据种类\n2.区间\n");
		printf("输入区间左端点:");
		scanf("%lf",&x);
		printf("输入区间右端点:");
		scanf("%lf",&x1);x1=(x+x1)/2.;
		break;
 }
while(fabs(fun(x1)/fun1(x1))>0.00005)
{
x=x1-fun(x1)/fun1(x1);
x1=x;
i++;
}
printf("方程的根:%lf\n",x1); 
printf("迭代次数:%d\n\n",i);
system("pause");
}

4. 弦割法

弦割法(Secant Method)是基于牛顿法的一种改进,基本思想是用弦的斜率近似代替目标函数的切线斜率,并用割线与横轴交点的横坐标作为方程式的根的近似。

SecantMethod

公式就不推了,参见维基百科或者百度百科。

#include"math.h"
#include"stdio.h"
#include"stdlib.h"
double fun(double k)
{
	return k*k*k-k*k-1;//所求方程 
}
main()
{double a,b,x,x1,l=1,x0,x2;
int i=0,p;
printf("No.0007弦割法求方程的根\n\n选择输入种类:\n1.单点\n2.双点\n");
printf("\n");
while(l==1)
{scanf("%d",&p);
if(p!=1&&p!=2) printf("请输入指定序号\n\n");//判断输入的序号是否正确 
else l=0;
}
switch(p)
{
 case 1:
		printf("种类\n1.单点\n");
		printf("输入点1:");
		scanf("%lf",&x);
		printf("输入点2:");
		scanf("%lf",&x1);
        while(fabs(fun(x1)*(x1-x)/(fun(x1)-fun(x)))>0.00005)
        {
        x2=x1-fun(x1)*(x1-x)/(fun(x1)-fun(x));
        x1=x2;
        i++;
        }
        printf("方程的根:%lf\n",x1); 
        printf("迭代次数:%d\n\n",i);
		break;
 case 2:printf("种类\n2.双点\n");
		printf("输入点1:");
		scanf("%lf",&x);
		printf("输入点2:");
		scanf("%lf",&x1);
        while(fabs(fun(x1)*(x1-x)/(fun(x1)-fun(x)))>0.00005)
        {
        x2=x1-fun(x1)*(x1-x)/(fun(x1)-fun(x));
        x=x1;
        x1=x2;
        i++;
        }
        printf("方程的根:%lf\n",x1); 
        printf("迭代次数:%d\n\n",i);
	    break;
}
system("pause");