1. 程式人生 > >牛頓迭代

牛頓迭代

牛頓迭代法Newton's method

又叫“牛頓-拉弗森方法”(Newton-Raphson method它是一種在實數域和複數域上近似求解方程的方法,方法是使用f(x)泰勒級數前幾項來尋找f(y) = 0的根。

原理

對於非線性方程同樣適用

總之,牛頓迭代公式:

             

應用

求某些方程的根

 1 double a, b, c, d;
 2 const double esp = 1e-6;
 3 
 4 double f(double x){
 5     return
a * x * x * x + b * x * x + c * x + d; 6 } 7 8 double fd(double x){ 9 return 3 * a * x *x + 2 * b * x + c; 10 } 11 12 //求解ax^3 + bx^2 + cx + d = 0的一個根 13 double newton(double x) 14 { 15 while (fabs(f(x)) > esp){x = x - f(x) / fd(x);} 16 return x; 17 }

如果想求出一個範圍內的所有的跟,則可以在該範圍內列舉初始值x,來逼近根的值。

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<vector>
 4 using namespace std;
 5 
 6 double a, b, c,d;
 7 const int INF = 0x3f3f3f3f;
 8 const int maxn = 2;
 9 const double esp = 1e-6;
10 double Abs(double x)
11 {
12     return x >= 0 ? x : -x;
13 }
14 double f(double
x) 15 { 16 return a * x * x * x + b * x * x + c * x + d; 17 } 18 19 //需要f的導數在適當的區間內絕對值不大於於某個小於1的正數 20 double fd(double x) 21 { 22 return 3 * a * x *x + 2 * b * x + c; 23 } 24 25 //求解ax^3 + bx^2 + cx + d = 0的所有根 26 void newton() 27 { 28 vector<double>ans; 29 //在一個大區域中逐個點用牛頓法,可找出大多數3次方程所有根 30 for (int x0 = -maxn; x0 < maxn; x0++) 31 { 32 double x1 = x0; 33 int cnt = 0; //迭代次數 34 while (Abs(f(x1)) > esp) 35 { 36 if ((++cnt) > 10000) break; //迭代次數超過1000,認為方程無解 37 double x = x1; 38 x1 = x - f(x) / fd(x); 39 } 40 if (cnt > 10000) continue; 41 int flag = 0; 42 for(int i = 0;i < ans.size();i++) 43 if (Abs(ans[i] - x1) < 0.01) 44 { 45 flag = 1; 46 break; 47 } 48 if (!flag && x1 < INF && x1 > -INF) ans.push_back(x1); //x1==inf || -inf是在極值點,並不一定是方程的根 49 } 50 if (ans.size() == 0) printf("無解\n"); 51 else 52 { 53 for (int i = 0; i < ans.size(); i++) 54 printf("%lf ", ans[i]); 55 printf("\n"); 56 } 57 } 58 59 int main() 60 { 61 while (scanf("%lf%lf%lf%lf",&a,&b,&c,&d) == 4) 62 newton(); 63 64 return 0; 65 }
View Code

(這個程式碼測試起來有很多錯誤,有好的意見歡迎留言)

高精度開根號

對於一個已知的數 a,開根號本質上是求一個X,使得 X2=a,即X2 - a = 0的根。

由前面易知迭代公式Xn+1 = Xn - (Xn2 - a) / 2Xn = (Xn + a / Xn) / 2。

實際操作還需要套一個高精度除法。

缺點

並不能求解所有方程的根,而且得到的只是近似值,不是準確值。

收斂的充分條件:

若 f 二階可導,那麼在待求的零點 x 周圍存在一個區域,只要起始點 x0 位於這個臨近區域內,那麼牛頓-拉弗森方法必定收斂。

駐點

 

從代數上看,導數為0,無法迭代出下一個值。

越來越遠的不收斂

迴圈震盪的不收斂

 

參考連結:

https://blog.csdn.net/wubaizhe/article/details/75574798

https://baike.baidu.com/item/牛頓迭代法/10887580?fr=aladdin#2

https://zh.wikipedia.org/wiki/牛頓法

https://www.zhihu.com/question/20690553