转自:https://blog.youkuaiyun.com/howroad/article/details/79284465
牛顿迭代法:
随便找一个曲线上的A点,做一个切线,切线的根与曲线的根还有一定的距离。从这个切线的根出发,做一根垂线,和曲线相交于B点,继续重复刚才的工作,经过多次迭代会越来越接近 曲线的根,迭代收敛.
方程f(x)-M=0;
二次方程,首先不考虑震荡/多根/远离等情况
首先随意给一个值 x0,得到过该点的切线方程
f’(x0)(x-x0)+f(x0)=0;
求得该切线的跟
x1=x0-f(x0)/f’(x0);
从图像上看x1比x0更接近原始方程的解.
再求点(x1,f(x1))的切线方程;
f’(x1)(x-x1)+f(x1)=0;
根为:x2=x1-f(x1)/f’(x1);
x2比x1更接近方程的解
…
所以若干次重复后,xn就是非常接近二次方程的解.
其中f’(x)=2x;x0为随便的一个数字;f(x)=x^2-m
用java傻瓜方式写出来如下:
public static void main(String[] args) {
System.out.println(sqrt(2));//1.414213562373095
}
public static double sqrt(double m) {
double x=5201314;//随便给一个数
for(int i=0;i<30;i++) {//迭代50次,求过切线的根x的切线的根...
x=(x*x+m)/2/x;
}
return x;
}
便于理解把这个方程拆成以下几个
public static double sqrt2(double m) {
double x0=1.0;//随便给一个值
for(int i=0;i<20;i++) {//重复20次
x0= myGetX(x0,m);
}
return x0;
}
public static double myGetY(double x,double m) {
return x*x-m;
}
public static double myGetX(double x,double m) {
return x-myGetY(x,m)/2/x;
}
最终版
public static double sqrt3(double c) {
if(c<0) return Double.NaN;
double err=1e-15;//定义一个很小的误差
double t=c;
while(Math.abs(t-c/t)>err*t) {//实际上为t^2-c>err,表示最终结果和真实的平方根相差不超过1的负15次方
t=(c/t+t)/2.0;
}
return t;
}