迭代法是用於求方程或方程組近似根的一種常用的算法設計方法。設方程為f(x)=0,用某種數學方法導出等價的形式x=g(x),然后按以下步驟執行:
(1)選一個方程的近似根,賦給變量x0。
(2)將x0的值保存於變量x1,然后計算g(x1),並將結果存於變量x0。
(3)當x0與x1的差的絕對值還小於指定的精度要求時,重復步驟(2)的計算。
若方程有根,並且用上述方法計算出來的近似根序列收斂,則按上述方法求得的x0就認為是方程的根。上述算法用C++程序的形式表示為:
x0=初始近似根;
do {
x1=x0;
x0=g(x1); // 按特定的方程計算新的近似根
} while ( fabs(x0-x1)>Epsilon);
cout<<“方程的近似根是”<<x0;
例如,采用迭代法求方程x=cos(x)一個根的源程序為:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
float x0,x1=0.0;
while(1)
{
x0=x1;
x1=cos(x0);
if (fabs(x0-x1)<1e-6)
break;
}
cout<<"The real root is "<<x1<<endl;
return 0;
}
【例3】編寫一個程序,用迭代法求方程x3-x-1=0在區間[0,2]中的根。
(1)編程思路1。
用二分迭代法求解。
二分迭代法的原理:先取方程f(x)=0的兩個粗略解 x1和x2,若f(x1)與f(x2)的正負符號相反,則表明區間(x1,x2)中至少有方程的一個解。如果f(x)在區間(x1,x2)內單調遞增或單調遞減,則(x1,x2)內只有方程的一個解。具體做法:取x1,x2的中點x3,計算f(x3)的值。在x1,x2中去掉函數值與f(x3)同號者(假設f(x2)和f(x3)同號),得到一個由x1和x3構成的區間,這個區間是原來的一半,並且包含精確解。不斷重復(不是無窮多次)上述步驟,可以得到一個序列:x1,x2,x3,…,xn+1,xn,…這個序列的極限便是方程的精確值。
(2)源程序1。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double x1,x2,x3 ;
x1 = 0; x2 = 2 ; // 初始區間
do
{
x3 = (x1 + x2) / 2;
if ((x1 * x1 * x1 - x1 - 1) * (x3 * x3*x3 - x3 - 1) > 0 )
x1 = x3 ; // 改變區間
else
x2 = x3 ; // 改變區間
} while (fabs(x2-x1)>0.000001); // 判斷是否滿足精度要求
cout<<x1<<endl; // 輸出結果
return 0 ;
}
(3)編程思路2。
用牛頓迭代法求解。
牛頓迭代法的基本原理是:設已知方程的近似根x0,則在x0附近f(x)可用一階泰勒多項式
近似代替。因此,方程f(x)=0可近似地表示為p(x)=0,用x1表示p(x)=0的根,它與f(x)=0的根差異不大。
設f'(x0)!=0,由於x1滿足,解得
重復這一過程,得到迭代公式:
牛頓迭代法的幾何解析是:在x0處作曲線的切線,切線方程為
。
令y=0,可得切線與x軸的交點坐標
這就是牛頓法的迭代公式。因此,牛頓法又稱“切線法”。
(4)源程序2。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double x1,x2 ;
x1 = x2 = 2 ; // 初始點 x0=2
do
{
x1 = x2;
x2= x1- (x1 * x1 * x1 - x1 - 1)/ (3* x1 * x1 - 1) ;
} while (fabs(x2-x1)>0.000001); // 判斷是否滿足精度要求
cout<<"方程的一個根為 "<<x2<<endl;
return 0 ;
}
(5)編程思路3。
用弦截法求解。
弦截法是在牛頓法的基礎上得出的求解非線性方程的一種十分重要的插值方法。用牛頓法求解非線性方程f(x)=0的根時,每一步都要計算導數值,如果函數f(x)比較復雜時,計算導數f'(x)往往比較困難。而弦截法使用差商來代替牛頓法中的導數值進行迭代,避免了計算函數的導數值,並且收斂速度很快。
弦截法的算法步驟如下:
1)確定初始值x0,x1;
2)計算函數值f(x0),f(x1);
3)利用迭代公式 計算方程新的近似根值x;
4)若滿足時便可停止迭代,x作為方程f(x)=0的近似根,算法結束;否則取x0=x1,x1=x,轉第(2)步,重復迭代計算x,直到滿足要求。
(6) 源程序3。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double x0,x1,x,f0,f1 ;
x1 =0; x = 2 ; // 初始區間
do
{
x0=x1; x1=x;
f0= x0 * x0 * x0 - x0 - 1 ;
f1= x1 * x1 * x1 - x1 - 1 ;
x=x1-f1/(f1-f0)*(x1-x0);
} while (fabs(x-x1)>0.000001); // 判斷是否滿足精度要求
cout<<"方程的一個根為 "<<x<<endl;
return 0 ;
}
比較牛頓迭代法和弦截法可知:
牛頓法是用切線與x軸的交點,逼近曲線f(x)與x軸的交點。迭代公式為
。
弦截法是用兩點之間的連線與x軸的交點,逼近曲線f(x)與x軸的交點。迭代公式為
。