参考书目:《数值分析》
y=x*x-a求零点 用零点附近(这里起始取的a/2,因为牛顿迭代左右均收敛,所以不会出现迭代发散的状况)抛物线切线与x轴所截的交点,在以交点做抛物线的切线继续求交点,进而不断迭代来近似抛物线的零点 由于该函数在零点附近是收敛的(二阶收敛)所以能不断迭代。而对于y=x*x*x-a函数则不一定行,如果a大于0,会存在三个根,对于第二个根,牛顿迭代则不会收敛。以后补上matlab图像。最终推导出迭代公式x1=(x0+a/x0)/2。
测试结果如下:
可以看出牛顿迭代速度远远快于二分求根
//main函数入口
#include <stdio.h>
#include <math.h>
double sqrt1(double a,int tot);
double sqrt2(double a,int tot);
double sqrt3(double a,int tot);
int main(void)
{
double i;
int j;
printf("input number to be sqrt:\n");
scanf("%lf %d",&i,&j);
printf("sqrt number is \n%.9f \n%.9f \n%.9f",sqrt1(i,j),sqrt2(i,j),sqrt3(i,1E-10));
return 0;
}
double sqrt1(double a,int tot)//传入二分迭代次数
{
double x,y;
int i;
x=a/2;
for(i=0;i<tot;i++)
{
y=(x+a/x)/2;
x=y;
}
return y;
}
double sqrt2(double a,int tot)
{
int i;
double low,mid,high;
low=0;
high=a>1?a:1; //避免在0到1之间的因变量超过自变量的区间
mid=(low+high)/2;
for(i=0;mid*mid!=a&&i<tot;i++)//如果直接相等退出循环
{
if(mid*mid<a)
{
low=mid;
mid=(low+high)/2;
}
else
{
high=mid;
mid=(low+high)/2;
}
}
return mid;
}
double sqrt3(double a,int err) //传入误差限
{
double x,y,temp;
temp=a/2;
do{
x=temp; //temp保留中间结果 方便x,y的比较
temp=(x+a/x)/2;
y=temp;
}while(fabs(x-y)>err);
return y;
}