牛頓迭代法是一種數值算法,能夠用於求函數的零點。其思想在於把函數抽象爲直線,一步步用估計逼近函數的零點。ios
其逼近速度很是有效,經常在十幾步迭代內就能求得很是精確的結果,十分高效。算法
考慮在以下座標系\(xOy\)中的一條直線:函數
其值在\(x=x_0\)時取值爲\(y_0\)。那麼這條直線與\(x\)軸的交點的\(x\)座標\(A\)爲多少?spa
設這條直線的解析式爲\(y=kx+b\),則有
\[ y_0=kx_0+b \]3d
即
\[ b=y_0-kx_0 \]code
令\(y=0\),得方程
\[ kx+y_0-kx_0=0 \]blog
解得
\[ x=\frac{kx_0-y_0}{k} \]io
即class
\[ x=x_0-\frac{y_0}{k} \]stream
咱們正式開始使用牛頓迭代法求函數\(f(x)\)的零點。
問題:試求\(\sqrt{2}\)的近似值。
原命題等價於求函數\(f(x)=x^2-2\)的零點。
首先咱們隨便猜想一個值。不妨設爲\(x=4\)吧。
過\((x,f(x))\)點做\(f(x)\)的切線,獲得:
根據導數的幾何意義,這條直線的斜率爲\(f'(x)\),則根據咱們前面獲得的結論,這個函數與\(x\)軸的交點的\(x\)座標爲
\[ x'=x-\frac{f(x)}{f'(x)} \]
根據最理想的估計,若是導數不變的話,零點應該就在那個位置。那麼咱們令\(x=x'\),這稱爲一次迭代。
回到例子。\(f(x)=x^2-2\),則\(f'(x)=2x\),則有:
\[ x'=x-\frac{f(x)}{f'(x)}=x-\frac{x^2-2}{2x}=\frac{x}{2}+\frac{1}{x} \]
每次用\(\frac{x}{2}+\frac{1}{x}\)替代\(x\),重複以上過程:
能夠看到,僅僅進行了六次迭代,就獲得了\(20\)位的精確值。
程序以下:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; const double eps=1e-10; double a,x; double f(double x){return x*x-a;} double df(double x){return 2*x;} int main(){ scanf("%lf",&a); x=1; while(fabs(f(x))>=eps)x-=f(x)/df(x); printf("%.10lf\n",x); }