利用牛顿迭代法来求平方根。

设r是  的根,选取  作为r的初始近似值,过点  做曲线  的切线L,L的方程为  ,求出L与x轴交点的横坐标 ,称x1为r的一次近似值。过点  做曲线  的切线,并求该切线与x轴交点的横坐标  ,称  为r的二次近似值。重复以上过程,得r的近似值序列,其中,  称为r的  次近似值,上式称为牛顿迭代公式。

对于x2=a,求a的平方根来说,相当于f(x)=x2-a,求曲线与x轴的交点。由上述结论可推导,xn+1=xn-f(x)/(2xn),假设要求平方根的数为a,xn+1约等于xn,则平方根xn+1约等于x-(x2-a)/(2x),即(x/2+a/2x)。

  1. 这时, 曲线f(t) = t2 - a 上对应的点为(t, t2 - a), 过这个点切线的斜率为2t

  2. 如果我们把这一步迭代根的逼近距离(下图横轴红色表示)设为d, 那么结合1我们有: 2t = (t2 - a) / d

  3. 所以 d = (t - a/t)2, 这一步迭代后根坐标为(t - d, 0), 即(t + a/t)/2

  4. 判断精度,如果精度满足跳出迭代,如果不满足,重复step1.

public double sqrt(double x){
         //防止传入的参数小于0
         if(x<0){
               return Double.NaN;
         }
         double eps=1e-12;//保留小数点位数
         double t=x;
         //条件还可以这样写 while(Math.abs(t-x/t)>eps*t)
         while(Math.abs(t*t-x)>eps){
                 t=(t+x/t)/2.0;
         }
         return t;
}

 进一步优化

//求x的平方根
public double sqrt(double x){
         //防止传入参数小于0
         if(x<0){
                 return Double.NaN;
         }
         double eps=1e-15; //精确度
         double m=x; //第i个值
         double n; //第i+1个值
         do{
                n=m;
                m=(m+x/m)/2.0;
         }while(Math.abs(m-n)>eps);
         return m;
}

扩展之后,求x的三次方根

public double cbrt(double x){
         double m=x;
         double eps=1e-15;
         double n;
         do{
               n=m;
               m=(2*m+x/(m*m))/3.0;
         }while(Math.abs(m-n)>eps);
         return m;
}

 

 posted on 2018-05-16 20:58  会飞的金鱼  阅读(1129)  评论(0)    收藏  举报