不使用Math.sqrt实现求平方根
利用牛顿迭代法来求平方根。
设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)。
这时, 曲线f(t) = t2 - a 上对应的点为(t, t2- a), 过这个点切线的斜率为2t
如果我们把这一步迭代根的逼近距离(下图横轴红色表示)设为d, 那么结合1我们有: 2t = (t2 - a) / d
所以 d = (t - a/t)2, 这一步迭代后根坐标为(t - d, 0), 即(t + a/t)/2
判断精度,如果精度满足跳出迭代,如果不满足,重复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; }优质内容筛选与推荐>>