如何使用牛顿迭代开根号Newton iteration
一般说到整数的开根号其实我们都可以用很简单的二分法来解决,但是如果是浮点数的话则一般来说更多人一开始想到的方式就是使用牛顿迭代法来完成。
牛顿迭代这个名字听起来好像非常的高大上,但是其实也算是比较基础的数学,让我们来分析一下牛顿迭代到底是怎么样解决开更好的问题吧。
首先我们来看一下求根的函数式
f
(
x
)
=
x
2
−
v
f(x) = x^2 - v
f(x)=x2−v 当
f
(
x
)
=
0
f(x) = 0
f(x)=0的时候,x就是
v
\sqrt v
v 了。看到这里其实都非常的容易理解。但是看牛顿迭代的话我们最好还是通过图像来理解。假设原点为 o, 当v = 4的时候,我们的函数
f
(
x
)
=
x
2
−
v
f(x) = x^2-v
f(x)=x2−v 会在 x = 2的位置和x轴相交。我们沿着函数f(x)上的任意一点做切线。假设在x = v的位置做切线,再将这一个切线和x轴相交的位置设为点T。我们可以根据我们的原函数得出切线的斜率为2x。
在得知斜率等于2x的时候,我们就可以算出从v到t的距离 = f(x)/2x 。从原点O到T的的距离OT则是我们需要不段进行更新迭代的值,而
O
T
=
O
V
−
T
V
=
v
−
f
(
x
)
/
2
OT = OV-TV = v - f(x)/2
OT=OV−TV=v−f(x)/2 我们把
f
(
x
)
=
x
2
−
v
f(x) = x^2-v
f(x)=x2−v带入公式就可以得到
O
T
=
x
−
(
x
2
−
v
)
/
2
x
=
x
−
(
x
/
2
−
v
/
2
x
)
=
x
/
2
+
v
/
2
x
=
(
x
+
v
/
x
)
/
2
OT = x-(x^2-v)/2x= x-(x/2-v/2x) = x/2 + v/2x = (x+v/x)/2
OT=x−(x2−v)/2x=x−(x/2−v/2x)=x/2+v/2x=(x+v/x)/2。 所以我们最终得到的OT的公式就是
(
x
+
v
/
x
)
/
2
(x+v/x)/2
(x+v/x)/2
我们不断的绩算新的这个值肯定会比当前的C更加接近我们希望求得的值,但是迭代法什么时候停下来呢?这个时候就要看我们给出的阈值了,当f(x) 小于特定阈值的的时候就可以停止了。
让我们看看java的实现吧
class Sqrt{
public static double sqrt(double v, double err){
if(v < 0){
return Double.NaN;
}
double t = v;
while(Math.abs(t-v/t) > err*t){
t = (v/t+t)/2;
}
return t;
}
}
这样我们就可以求出给定误差值的根号了。