1實(shí)驗(yàn)內(nèi)容
用迭代法求下列方程的根
f(x)=x3+2x2+10x-20=0 (x*=1.368808107821372...),要求誤差< 10-15 嫉拐。
(1)把方程改寫成等價(jià)的迭代格式:
x(k+1) =20/(xk^2+2xk+10)魁兼,取初值x0=1, 求方程的根漠嵌。
(2)把方程改寫成等價(jià)的迭代格式:
xk+1 = 2-(xk3+2xk2)/10儒鹿,取初值x0=1, 求方程的根几晤。
(3)對(duì)迭代格式(1)和(2)分別用Aitken法進(jìn)行加速,并對(duì)結(jié)果進(jìn)行分析圾浅。
2 算法原理
2.1 不動(dòng)點(diǎn)迭代法
迭代法是一種逐次逼近的方法憾朴,用某種固定格式反復(fù)校正根的近似值,使之逐步精確灸拍,最后達(dá)到滿足精度要求的結(jié)果砾省。
方程f(x)=0化為等價(jià)形式的方程x=φ(x) ,構(gòu)造迭代公式xk+1=φ(xk), k=0,1,2,……取初始近似根(迭代初值)x0纤房,進(jìn)行迭代計(jì)算x1=φ(x0),x2=φ(x1),...,xk+1=φdf(xk),……
則有x1翻诉,x2 ,……,xk,……,得到迭代序列{xk}.如果這個(gè)序列有極限碰煌,則迭代公式是收斂的。
這時(shí)則x(x)蛾派,x稱為函數(shù)φ(x)的不動(dòng)點(diǎn)个少,等價(jià)地有f(x)=0,x*即為方程的根。連續(xù)函數(shù)φ(x)稱為迭代函數(shù)壳澳。
實(shí)際計(jì)算到|xk-xk-1|<ε(ε是預(yù)定的精度)茫经,取x*≈xk萎津。
迭代公式收斂指迭代序列{xk}收斂锉屈,迭代公式發(fā)散指迭代序列{xk}不收斂垮耳,即發(fā)散。迭代公式不一定總是收斂儡炼。簡(jiǎn)單迭代法的幾何意義如下:
圖2 收斂與發(fā)散的幾何對(duì)比
??=??(??) 的解稱為函數(shù) ??(??) 的不動(dòng)點(diǎn),幾何圖像為函數(shù)圖像與正比例函數(shù) ??=??的交點(diǎn)榜贴。迭代形式為:????+1=??(????) 。設(shè)函數(shù)的不動(dòng)點(diǎn)為 ???鹃共,當(dāng)|??′(???)|<1 時(shí)驶拱,在不動(dòng)點(diǎn)附近的存在一個(gè)領(lǐng)域,使得從領(lǐng)域內(nèi)的某個(gè)值開始的不動(dòng)點(diǎn)迭代收斂蓝纲,收斂到不動(dòng)點(diǎn)。通過(guò) ??????+1≈??′(???)??????式永丝,當(dāng)導(dǎo)數(shù)絕對(duì)值小于1時(shí)箭养,迭代后誤差的線性主部較迭代前誤差小,以導(dǎo)數(shù)絕對(duì)值為收斂常數(shù)線性收斂喝检。唯一不同的是若導(dǎo)數(shù)值為零撼泛,此時(shí)該迭代至少二次收斂。用不動(dòng)點(diǎn)迭代解非線性方程的核心在于將非線性方程轉(zhuǎn)化為一個(gè)收斂的不動(dòng)點(diǎn)迭代纺涤。
2.2 Aitken加速算法
Aitken加速收斂算法基本原理:
對(duì)于收斂的迭代過(guò)程,只要迭代足夠多次撩炊,就可以使結(jié)果達(dá)到任意的精度。但有時(shí)迭代過(guò)程收斂緩慢伯顶,從而使計(jì)算量變得很大骆膝,因此,迭代過(guò)程的加速是個(gè)重要的過(guò)程掐暮。
2.3 牛頓迭代法原理
牛頓迭代法是用于求解等式方程的一種方法政钟。類似于求解F(x)=0的根,牛頓迭代法求解的是近似根精算,這個(gè)想法準(zhǔn)確來(lái)說(shuō)來(lái)源于泰勒展開式碎连,需要求解的表達(dá)式可能非常復(fù)雜,通過(guò)一般的方法鱼辙,我們很難求出它的解。
所以采用了一種近似求解的方法前鹅,取泰勒展開式的前幾項(xiàng)峭梳,隊(duì)原來(lái)的求解函數(shù)做一個(gè)取代,然后捂寿,求解這個(gè)取代原方程的方程的解孵运,作為近似解。當(dāng)然只對(duì)原方程做一次近似求解不行驳概,因?yàn)榈谝淮谓瓶隙ú粫?huì)太準(zhǔn)確,所以還需要不斷地迭代顺又。
首先就要取一個(gè)值作為初始的近似值,然后去求解該點(diǎn)的泰勒展開近似項(xiàng)蹂空,然后求解根果录,之后再以此根對(duì)原方程進(jìn)行近似,然后再求解結(jié)果不斷重復(fù)迭代弱恒,最終就能求得近似解。
牛頓迭代法迭代公式如下:
設(shè)x是f(x) = 0的根分瘦,選取x0作為x初始近似值琉苇,過(guò)點(diǎn)(x0, f(x))做曲線y = f(x)的切線L并扇,則L的方程為y = f(x0)+f '(x0)(x-x0)抡诞,求出L與x軸交點(diǎn)的橫坐標(biāo)x1= x0-f(x0) / f '(x0),稱x1為x的一次近似值肴熏。過(guò)點(diǎn)(x1, f(x1))做曲線y = f(x)的切線顷窒,并求該切線與x軸交點(diǎn)的橫坐標(biāo)x2= x1-f(x1)/ f '(x1),稱x2為x的二次近似值鸦做。重復(fù)以上過(guò)程谓着,得r的近似值序列,其中xn+1=x(nf(xn)/f'(xn)治筒,稱為x的n+1次近似值,上式稱為牛頓迭代公式耸袜。
解非線性方程f(x)=0的牛頓法是把非線性方程線性化的一種近似方法。把f(x)在x0點(diǎn)附近展開成泰勒級(jí)數(shù)f(x) = f(x0)+(x-x0)f'(x0)+(x-x0)2*f''(x0)/2! +… 取其線性部分(一次)夷陋,作為非線性方程f(x) = 0的近似方程胰锌,即泰勒展開的前兩項(xiàng),則有f(x0)+f'(x0)(x-x0)=0 設(shè)f'(x0)≠0則其解為x1=x0-f(x0)/f'(x0) 這樣酬土,得到牛頓法的一個(gè)迭代序列:x(n+1)= xn-f(xn) / f '(xn)格带。
牛頓迭代法,取得是泰勒展開式的前兩項(xiàng)屈呕,也就是線性近似棺亭,所以迭代比較快,容易計(jì)算嗽桩。
3 程序框圖
4 編程實(shí)現(xiàn)
利用所編程序碌冶,求解下列方程的根:
以下將用Python進(jìn)行編程實(shí)驗(yàn)涝缝,利用不動(dòng)點(diǎn)迭代法與牛頓迭代法求解題目中方程的根,并且利用Aitken加速方法對(duì)其進(jìn)行加速嫩挤,最后進(jìn)行結(jié)果分析與討論。
利用不動(dòng)點(diǎn)迭代法的Python代碼詳解及運(yùn)行結(jié)果:
(1) 把方程改寫成等價(jià)的迭代格式: xk+1+20/(xk2+2xk+10)岂昭,取初值x0=1,求方程的根邑遏。
第(1)種迭代格式代碼詳解:
from sympy import *
def fun():
"""
求解方程的符號(hào)定義
:return:方程
error:這里不能用math庫(kù)中的函數(shù)恰矩,pow()需要調(diào)用符號(hào)庫(kù)中的函數(shù),即sympy.pow()
或者用from sympy import * 來(lái)導(dǎo)入sympy中的所有函數(shù)纪吮,之后直接寫pow()函數(shù)即
是默認(rèn)的sympy中的函數(shù)萎胰。
"""
x = symbols('x') # 符號(hào)變量的定義
# return 2 * exp(-x) * sin(x) + 2 * cos(x) - 0.25
return pow(x, 3) + 2.0 * pow(x, 2) + 10.0 * x - 20.0 # 返回函數(shù)的值
def fixedPoint(x0, eps, maxIter):
"""
不動(dòng)點(diǎn)迭代法的作用是,求解非線性方程的根冰肴,采用逐步逼近的方法進(jìn)行計(jì)算
:param x0:迭代初值
:param eps:誤差精度要求
:param maxIter:最大迭代次數(shù)
:return:返回值為None
"""
x = symbols('x')
fh = fun()
x_n = x0 # 定義初值
k = 0 # 初始化迭代次數(shù)
errval = 0 # 初始化誤差
print('%3s %10s %18s' % ('迭代次數(shù)', '方程近似值', '迭代誤差'))
for k in range(maxIter):
x_b = x_n # 代表x_n
x_n = 20 / (pow(x_b, 2) + 2 * x_b + 10) # 寫出第一種迭代函數(shù)格式
errval = abs(fh.evalf(subs={x: x_n})) # 第k次迭代誤差的大小
print('%3d %22.15f %22.15f' % (k + 1, x_n, errval)) # 分別輸出迭代次數(shù)榔组,方程的近似根以及迭代誤差
if errval <= eps:
break
if k + 1 <= maxIter - 1:
print('方程在滿足精度' + str(eps) + '的條件下,近似解為:'
+ str(x_n) + ',誤差為:' + str(errval))
else:
print('不動(dòng)點(diǎn)迭代法求解方程的根检痰,已經(jīng)達(dá)到最大迭代次數(shù)锨推,也可能不收斂或精度過(guò)高...')
return None
if __name__ == '__main__':
fh = fun()
plot(fh)
x0 = float(input('請(qǐng)輸入迭代初值:')) # input函數(shù)總是以字符串的形式返回
eps = float(input('請(qǐng)輸入誤差精度要求:')) # 方程解的精度要求是近似解與真值之間的誤差
maxIter = int(input('請(qǐng)輸入最大迭代次數(shù):')) # 方程一般會(huì)迭代無(wú)數(shù)次,必須定義其迭代的次數(shù),以求收斂
fixedPoint(x0, eps, maxIter)
print('方程為:', '%30s' % (str(fun())))
print('迭代函數(shù)為:', '%20s' % ('20 / (x**2 + 2 * x + 10)'))
(2) 把方程改寫成等價(jià)的迭代格式: xk+1 = 2-(xk3+2xk2)/10锦担,取初值x0=1, 求方程的根洞渔。
第二種迭代格式代碼詳解:
from sympy import *
def fun():
"""
求解方程的符號(hào)定義
:return:方程
error:這里不能用math庫(kù)中的函數(shù)缚态,pow()需要調(diào)用符號(hào)庫(kù)中的函數(shù),即sympy.pow()
或者用from sympy import * 來(lái)導(dǎo)入sympy中的所有函數(shù)玫芦,之后直接寫pow()函數(shù)即
是默認(rèn)的sympy中的函數(shù)。
"""
x = symbols('x') # 符號(hào)變量的定義
# return 2 * exp(-x) * sin(x) + 2 * cos(x) - 0.25
return pow(x, 3) + 2.0 * pow(x, 2) + 10.0 * x - 20.0 # 返回函數(shù)的值
def fixedPoint(x0, eps, maxIter):
"""
不動(dòng)點(diǎn)迭代法的作用是医增,求解非線性方程的根,采用逐步逼近的方法進(jìn)行計(jì)算
:param x0:迭代初值
:param eps:誤差精度要求
:param maxIter:最大迭代次數(shù)
:return:返回值為None
"""
x = symbols('x')
fh = fun()
x_n = x0 # 定義初值
k = 0 # 初始化迭代次數(shù)
errval = 0 # 初始化誤差
print('%3s %10s %18s' % ('迭代次數(shù)', '方程近似值', '迭代誤差'))
for k in range(maxIter):
x_b = x_n # 代表x_n
x_n = 2 - (pow(x_b, 3) + 2 * pow(x_b, 2))/10 # 寫出第二種迭代函數(shù)格式
errval = abs(fh.evalf(subs={x: x_n})) # 第k次迭代誤差的大小
print('%3d %22.15f %22.15f' % (k + 1, x_n, errval)) # 分別輸出迭代次數(shù)叶骨,方程的近似根以及迭代誤差
if errval <= eps:
break
if k + 1 <= maxIter - 1:
print('方程在滿足精度' + str(eps) + '的條件下,近似解為:'
+ str(x_n) + ',誤差為:' + str(errval))
else:
print('不動(dòng)點(diǎn)迭代法求解方程的根天揖,已經(jīng)達(dá)到最大迭代次數(shù)跪帝,也可能不收斂或精度過(guò)高...')
return None
if __name__ == '__main__':
fh = fun()
plot(fh)
x0 = float(input('請(qǐng)輸入迭代初值:')) # input函數(shù)總是以字符串的形式返回
eps = float(input('請(qǐng)輸入誤差精度要求:')) # 方程解的精度要求是近似解與真值之間的誤差
maxIter = int(input('請(qǐng)輸入最大迭代次數(shù):')) # 方程一般會(huì)迭代無(wú)數(shù)次,必須定義其迭代的次數(shù)万细,以求收斂
fixedPoint(x0, eps, maxIter)
print('方程為:', '%30s' % (str(fun())))
print('迭代函數(shù)為:', '%20s' % ('2 - (x**3 + 2 * x**2)/10'))
(3) 對(duì)迭代格式(1)和(2)分別用Aitken法進(jìn)行加速赖钞,并對(duì)結(jié)果進(jìn)行分析聘裁。
迭代格式
第(1)種迭代格式Aitken加速法代碼詳解:
from sympy import *
def Aitken(x0, eps, iterNum, Phi):
xk_1 = x0
errval = 0
print('%3s %10s %18s' % ('迭代次數(shù)', '方程近似值', '迭代誤差'))
for k in range(iterNum):
y = Phi(xk_1)
z = Phi(y)
if (z - 2 * y + xk_1) != 0:
xk = xk_1 - (y - xk_1) ** 2 / (z - 2 * y + xk_1)
errval = abs(xk - xk_1)
print('%3d %22.15f %22.15f' % (k + 1, xk, errval))
if errval < eps:
return xk
else:
xk_1 = xk
else:
return xk
print('方法失敗')
return 0
def Phi(x):
return 20 / (pow(x, 2) + 2 * x + 10)
if __name__ == '__main__':
x = symbols('x')
x0 = float(input('請(qǐng)輸入迭代初值:')) # input函數(shù)總是以字符串形式返回
eps = float(input('請(qǐng)輸入迭代誤差精度要求:')) # 方程誤差精度要求為迭代近似值與真值之間的差值
iterNum = int(input('請(qǐng)輸入最大迭代次數(shù):')) # 最大迭代次數(shù)限制了方程的收斂
Phi(x)
Aitken(x0, eps, iterNum, Phi)
第(2)種迭代格式Aitken加速法代碼詳解:
from sympy import *
def Aitken(x0, eps, iterNum, Phi):
xk_1 = x0
errval = 0
print('%3s %10s %18s' % ('迭代次數(shù)', '方程近似值', '迭代誤差'))
for k in range(iterNum):
y = Phi(xk_1)
z = Phi(y)
if (z - 2 * y + xk_1) != 0:
xk = xk_1 - (y - xk_1) ** 2 / (z - 2 * y + xk_1)
errval = abs(xk - xk_1)
print('%3d %22.15f %22.15f' % (k + 1, xk, errval))
if errval < eps:
return xk
else:
xk_1 = xk
else:
return xk
print('方法失敗')
return 0
def Phi(x):
return 2 - (pow(x, 3) + 2 * pow(x, 2))/10
if __name__ == '__main__':
x = symbols('x')
x0 = float(input('請(qǐng)輸入迭代初值:')) # input函數(shù)總是以字符串形式返回
eps = float(input('請(qǐng)輸入迭代誤差精度要求:')) # 方程誤差精度要求為迭代近似值與真值之間的差值
iterNum = int(input('請(qǐng)輸入最大迭代次數(shù):')) # 最大迭代次數(shù)限制了方程的收斂
Phi(x)
Aitken(x0, eps, iterNum, Phi)
牛頓迭代法代碼詳解:
from sympy import *
def fun():
"""
求解方程的符號(hào)定義
:return:方程
error:這里不能用math庫(kù)中的函數(shù)献起,pow()需要調(diào)用符號(hào)庫(kù)中的函數(shù)镣陕,即sympy.pow()
或者用from sympy import * 來(lái)導(dǎo)入sympy中的所有函數(shù),之后直接寫pow()函數(shù)即
是默認(rèn)的sympy中的函數(shù)呆抑。
"""
x = symbols('x') # 符號(hào)變量的定義
# return 2 * exp(-x) * sin(x) + 2 * cos(x) - 0.25
return pow(x, 3) + 2.0 * pow(x, 2) + 10.0 * x - 20.0 # 返回函數(shù)的值
def diffFun():
"""
求解方程的一階導(dǎo)數(shù)
:return: 一階導(dǎo)數(shù)
"""
return fun().diff()
def newtonIterative(x0, eps, maxIter):
"""
牛頓迭代函數(shù)的作用,求解非線性方程的根厌殉,采用逼近法的思想
:param x0:迭代初值
:param eps:誤差精度要求
:param maxIter:最大迭代次數(shù)
:return:返回值為None
"""
# x1 = x0 - f(x0)/f'(x0)==>x1 = x2 - f(x1)/f'(x1)...
x = symbols('x')
fh = fun() # 引用方程
dfh = diffFun() # 引用方程的一階導(dǎo)數(shù)
x_n = x0
k = 0
errval = 0
print('%3s %10s %18s' % ('迭代次數(shù)', '方程近似值', '迭代誤差'))
# 利用牛頓迭代法的思想逐步逼近精確解
for k in range(maxIter):
x_b = x_n # 代表x(n)
fx = fh.evalf(subs={x: x_b}) # 方程在x_n處的數(shù)值
dfx = dfh.evalf(subs={x: x_b}) # 一階導(dǎo)數(shù)方程在x_n處的方程
x_n = x_b - fx / dfx # 牛頓迭代公式
errval = abs(fh.evalf(subs={x: x_n})) # 第k次迭代誤差的大小
print('%3d %22.15f %22.15f' % (k + 1, x_n, errval))
if errval <= eps:
break
if k + 1 <= maxIter - 1:
print('方程在滿足精度' + str(eps) + '的條件下公罕,近似解為:'
+ str(x_n) + ',誤差為:' + str(errval))
else:
print('牛頓迭代法求解數(shù)值逼近,已經(jīng)達(dá)到最大迭代次數(shù)楼眷,也可能不收斂或精度過(guò)高...')
# print(x0, eps, maxIter)
return None
if __name__ == '__main__':
fh = fun()
dfh = diffFun()
plot(fh)
plot(dfh)
x0 = float(input('請(qǐng)輸入迭代初值:')) # input函數(shù)總是以字符串的形式返回
eps = float(input('請(qǐng)輸入誤差精度要求:')) # 方程解的精度要求是近似解與真值之間的誤差
maxIter = int(input('請(qǐng)輸入最大迭代次數(shù):')) # 方程一般會(huì)迭代無(wú)數(shù)次,必須定義其迭代的次數(shù)桥状,以求收斂
newtonIterative(x0, eps, maxIter)
print('方程為:', '%30s' % (str(fun())))
print('方程的導(dǎo)數(shù)為:' '%22s' % (str(diffFun())))
5 結(jié)果分析與討論
由方程的曲線可以看出辅斟,此方程的根在1附近只有一個(gè)根芦拿,因此迭代初值取1可以降低迭代次數(shù),節(jié)省迭代時(shí)間酵幕。
(1)從不動(dòng)點(diǎn)迭代法與牛頓迭代法的結(jié)果對(duì)比可以看出缓苛,在精度1e-15高精度的情況下,方程很難在100次迭代中得到近似解未桥。但是牛頓迭代法對(duì)于方程的收斂速度高于不動(dòng)點(diǎn)迭代法。
(2)在兩種不同的迭代格式下冬耿,從運(yùn)行結(jié)果來(lái)看:第(1)種迭代格式收斂,但由于精度過(guò)高日月,達(dá)到最大迭代次數(shù)缤骨;第(2)種迭代格式是發(fā)散的,不論精度绊起,都不會(huì)收斂。
(3)分別對(duì)兩種迭代格式用Aitken法進(jìn)行加速,結(jié)果可以看出兩種迭代格式在1e-15的高精度下瘫里,均處于收斂的情況。不同的是第(1)種迭代格式在4此迭代后收斂谨读,而第(2)種迭代格式卻需要5次迭代才能收斂。但通過(guò)Aitken法加速之后铐尚,出現(xiàn)了以下兩種情況:
1)由于精度過(guò)高引起的達(dá)到最大迭代次數(shù)的問(wèn)題得以解決,函數(shù)收斂宣增;
2)由于迭代格式的發(fā)散問(wèn)題導(dǎo)致無(wú)法求解方程,在加速的情況下帖旨,也可以很快收斂,進(jìn)一步說(shuō)明了Aitken加速法的巨大作用解阅。
6 參考:
[1]https://baike.baidu.com/item/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3%E6%B3%95/10887580?fr=aladdin
[2]https://blog.csdn.net/weixin_45720246/article/details/115916645
[3]https://www.freesion.com/article/6284628111/
[5]https://www.bilibili.com/video/BV1Lq4y1U7Hj?spm_id_from=333.999.0.0
[6]《數(shù)值分析》歐陽(yáng)潔等货抄。