利用牛顿迭代法求平方根

求n的平方根,先如果一推測值X0 = 1,然后依据下面公式求出X1,再将X1代入公式右边,继续求出X2…通过有效次迭代后就可以求出n的平方根,Xk+1

先让我们来验证下这个巧妙的方法准确性,来算下2的平方根 (Computed by Mathomatic)
1-> x_new = ( x_old + y/x_old )/2
y
(x_old + -----)
x_old
#1: x_new = ---------------
2
1-> calculate x_old 1
Enter y: 2
Enter initial x_old: 1
 x_new = 1.5
1-> calculate x_old 2
Enter y: 2
Enter initial x_old: 1
 x_new = 1.4166666666667
1-> calculate x_old 3
Enter y: 2
Enter initial x_old: 1
 x_new = 1.4142156862745
1-> calculate x_old 10
Enter y: 2
Enter initial x_old: 1
Convergence reached after 6 iterations.
 x_new = 1.4142135623731
...

可见,随着迭代次数的添加,运算值会愈发接近真实值。非常奇妙的算法,但是怎么来的呢? 查了下wikipedia和wolfram,原来算法的名字叫Newton’s Iteration (牛顿迭代法)。

以下是极其つまらない(boring)的数理介绍,不喜欢数学的言下之意也就是绝大部分人能够略过了。
简单推导

如果f(x)是关于X的函数:



求出f(x)的一阶导,即斜率:



简化等式得到:



然后利用得到的终于式进行迭代运算直至求到一个比較精确的惬意值,为什么能够用迭代法呢?理由是中值定理(Intermediate Value Theorem):

假设f函数在闭区间[a,b]内连续,必存在一点x使得f(x) = c,c是函数f在闭区间[a,b]内的一点

我们先推測一X初始值,比如1,当然地球人都知道除了1本身之外不论什么数的平方根都不会是1。然后代入初始值,通过迭代运算不断推进,逐步靠近精确值,直到得到我们主观觉得比較惬意的值为止。比如要求768的平方根,由于252 = 625,而302 = 900,我们可先代入一推測值26,然后迭代运算,得到较精确值:27.7128。

回到我们最開始的那个”莫名其妙”的公式,我们要求的是N的平方根,令x2 = n,如果一关于X的函数f(x)为:

f(X) = X2 - n

求f(X)的一阶导为:

f'(X) = 2X

代入前面求到的终于式中:

Xk+1 = Xk - (Xk2 - n)/2Xk

化简即得到我们最初提到的那个求平方根的奇妙公式了:


用泰勒公式推导

我之前介绍过在The Art and Science of C一书中实用到泰勒公式求平方根的算法,事实上牛顿迭代法也能够看作是泰勒公式(Taylor Series)的简化,先回想下泰勒公式:



仅保留等式右边前两项:



令f(X0+ε) = 0,得到:



再令X1 = X0 + ε0,得到ε1…依此类推可知:



转化为:


引申

从推导来看,事实上牛顿迭代法不仅能够用来求平方根,还能够求立方根,甚至更复杂的运算。

相同,我们还能够利用C语言来实现下那个最简单的求平方根的公式(虽然我们能够直接用sqrt()完毕)
#include <stdio.h>
#include <math.h>
#define N 768
main() {
float x=1;
int i;
for (i=1;i<=1000;i++) {  // recursion times : 1000
x = (x + N/x)/2;
}
printf("The square root of %d is %f/n",N,x);
}

原文地址:https://www.cnblogs.com/gcczhongduan/p/4304021.html