1. 程式人生 > >用牛頓法求方程的根(重點是平方根)

用牛頓法求方程的根(重點是平方根)

(二)牛頓迭代法

 牛頓迭代法(Newton's method)又稱為牛頓-拉夫遜方法(Newton-Raphson method),它是牛頓在17世紀提出的一種在實數域和複數域上近似求解方程的方法。多數方程不存在求根公式,因此求精確根非常困難,甚至不可能,從而尋找方程的近似根就顯得特別重要。方法使用函式f(x)的泰勒級數的前面幾項來尋找方程f(x) = 0的根。牛頓迭代法是求方程根的重要方法之一,其最大優點是在方程f(x) = 0的單根附近具有平方收斂,而且該法還可以用來求方程的重根、復根。另外該方法廣泛用於計算機程式設計中。

 設r是f(x) = 0的根,選取x0作為r初始近似值,過點(x0,f(x0))做曲線y = f(x)的切線L,L的方程為y = f(x0)+f'(x0)(x-x0),求出L與x軸交點的橫座標 x1 = x0-f(x0)/f'(x0),稱x1為r的一次近似值。

過點(x1,f(x1))做曲線y = f(x)的切線,並求該切線與x軸交點的橫座標 x2 = x1-f(x1)/f'(x1),稱x2為r的二次近似值。重複以上過程,得r的近似值序列,其中x(n+1)=x(n)-f(x(n))/f'(x(n)),稱為r的n+1次近似值,上式稱為牛頓迭代公式。

 根據牛頓迭代的原理,可以得到以下的計算sqrt(n)的迭代公式:X(n+1)=[X(n)+p/Xn]/2。詳細解釋見下文。

一般性的程式設計方法如下:

double sqr(double n) { 
    double k=1.0; 
    while(abs(k*k-n)>1e-9) { 
        k=(k+n/k)/2; 
    } 
    return k; 
}

(三)利用牛頓迭代法計算開平方根

這種演算法的原理很簡單,我們僅僅是不斷用(x,f(x))的切線來逼近方程x^2-a=0的根。根號a實際上就是x^2-a=0的一個正實根,這個函式的導數是2x。也就是說,函式上任一點(x,f(x))處的切線斜率是2x。那麼,x-f(x)/(2x)就是一個比x更接近的近似值。代入f(x)=x^2-a得到x-(x^2-a)/(2x),也就是(x+a/x)/2。

 過程如下:

首先隨便猜一個近似值x,然後不斷令x等於x和a/x的平均數,迭代個六七次後x的值就已經相當精確了。
例如,我想求根號2等於多少。假如我猜測的結果為4,雖然錯的離譜,但你可以看到使用牛頓迭代法後這個值很快就趨近於根號2了:

(       4  + 2/   4     ) / 2 = 2.25
(    2.25  + 2/   2.25  ) / 2 = 1.56944..
( 1.56944..+ 2/1.56944..) / 2 = 1.42189..
( 1.42189..+ 2/1.42189..) / 2 = 1.41423..

 下面用C語言實現一遍:

#include "stdio.h"
#include "math.h"

int main(void)
{
    double n,y=1.0;

    printf("請輸入一個需要求其平方根的數:");
    scanf("%lf",&n);

    // 反覆代入 x(k+1) = 0.5[x(k)+n/x(k)]
    while(fabs((1.0/2.0*(y+n/y))-y)>=0.00001)
    {
        y=1.0/2.0*(y+n/y);
        printf( "y=%lf\n", y );
    }
    printf("平方根為%f\n",y);
    return 0;
}
請輸入一個需要求其平方根的數:2
y=1.500000
y=1.416667
y=1.414216
平方根為1.414216

請輸入一個需要求其平方根的數:3
y=2.000000
y=1.750000
y=1.732143
y=1.732051
平方根為1.732051

更快的方法: