第十章数值分析.docx
- 文档编号:30703856
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:19
- 大小:41.20KB
第十章数值分析.docx
《第十章数值分析.docx》由会员分享,可在线阅读,更多相关《第十章数值分析.docx(19页珍藏版)》请在冰豆网上搜索。
第十章数值分析
第十九章 數值分析
19-1 遞迴
19-2 數值分析範例
二三十年前沒有電腦的時候,數值分析這個研究主題其計算過程通常是最令人畏懼的問題,所以通常要有一批工讀生日以繼夜從事計算工作,隨著電腦科技的進步許多數學家的數值分析結論才又被人從新驗證,並讚嘆其偉大。
數值分析大部份都在解決級數問題,級數問題如能充份理解遞迴的觀念答案即可迎刃而解,而遞迴在近十年的程式語言裏已列為標準配備,連VB也難脫俗,所以本章10-1節先強調基本遞迴的觀念及程式撰寫法,並以快速排序法為例先以遞迴法強調其程式的簡潔性,再以非遞迴法自行安排堆疊來說明遞迴的觀念,其次10-2節再以數值分析實際面對的問題如割線法(Secant)法解方程式的解及牛頓除差法(Newtondivided-difference)來解多項式的對應值,若讀者能充份了解以上問題的程式設計過程,相信都能解決所有的數值分析問題,筆者再強調一次千萬不要每一題都去找解答,一定要自己作才會有深刻的印象。
19-1 遞迴
所謂遞迴就是程序自己呼叫自己。
在程式設計的領域裏,有許多情況使用遞迴可以減輕程式設計的負擔,並增加程式的可讀性,就如同人類日常思考模式常有重覆某一件事直到什麼條件時結束。
所以遞迴也是一種特殊的迴路,尤其數值分析的問題用得最多。
範例19-1A 試以二分猜值法求輸入正數的平方根。
(本範例使用程序Sub)。
目 的
使讀者了解遞迴的使用。
輸出結果
程式列印
Rem19_1A
PrivateSubcmd_Click()
DimMsg,x1,x2
value=InputBox("","輸入正數","16")
x1=0:
x2=value:
x=value
sqrtx1,x2,x
Msg=value&"的其平方根是"&x
MsgBoxMsg
EndSub
PrivateSubsqrt(ByValx1,ByValx2,value)
Dimx3
IfAbs(x1-x2)<0.00000001Then
value=x1
ExitSub
EndIf
x3=(x1+x2)/2
Ifx3*x3-value<0Then
sqrtx3,x2,value
Else
sqrtx1,x3,value
EndIf
EndSub
程式說明
遞迴過程須變動的參數,必須用傳值法。
本例value參數使用傳址法傳回運算結果。
範例19-1B 以Function重作上範例。
程式列印
Rem19_1B
Dimx,valueAsDouble
PrivateSubcmd_Click()
DimMsg,x1,x2
value=InputBox("","輸入正數","16")
x1=0:
x2=value
x=sqrt(x1,x2)
Msg=value&"的其平方根是"&x
MsgBoxMsg
EndSub
PrivateFunctionsqrt(ByValx1,ByValx2)
IfAbs(x1-x2)<0.0000001Then
sqrt=x1
ExitFunction
EndIf
x=(x1+x2)/2
Ifx*x-value<0Then
sqrt=sqrt(x,x2)
Else
sqrt=sqrt(x1,x)
EndIf
EndFunction
範例19-1C 以遞迴法求算10+9+8+7...+1之和。
程式列印
Rem19_1C
PrivateSubcmd_Click()
d=sum(10)
Printd
EndSub
PrivateFunctionsum(mAsInteger)
Ifm<=1Then
sum=1
ExitFunction
Else
sum=m+sum(m-1)
EndIf
EndFunction
程式說明
以d=sum(4)解說
m=4執行Else sum=4+sum(3) 繼續呼叫sum函數
m=3執行Else sum=4+3+sum
(2) 繼續呼叫sum函數
m=2執行Else sum=4+3+2+sum
(1) 繼續呼叫sum函數
m=1執行Then sum=4+3+2+1 離開sum函數
範例19-1D 以遞迴法求費式數列。
執行結果
程式列印
Rem19_1D
PrivateSubcmd_Click()
DimkAsInteger
k=InputBox("","輸入欲求費式數列第幾項","7")
k=CInt(k)
d=fib(k)
frm.Print"f("&k&")="&d
EndSub
PrivateStaticFunctionfib(kAsInteger)
Ifk<=2Then
fib=1
ExitFunction
Else
fib=fib(k-1)+fib(k-2)
EndIf
EndFunction
程式解說
以d=fib(5)解說
fib(5)=fib(4)+fib(3)
=fib(3)+fib
(2)+fib(3)
=fib
(2)+fib
(1)+1+fib(3)
=1+1+1+fib
(2)+fib
(1)
=1+1+1+1+1(已無函數並結束遞迴)
=5
範例19-1E 試以遞迴法求輸入兩數的最大公因數(Gcd)。
輸出結果
程式列印
Rem19_1E
PrivateSubcmdend_Click()
End
EndSub
PrivateSubcmdstart_Click()
a=txta.Text
b=txtb.Text
Ifb>aThent=a:
a=b:
b=t
c=gcd(a,b)
cmdstart.Caption="gcd="&c
EndSub
PublicFunctiongcd(a,b)
Ifb=0Then
gcd=a
ExitFunction
Else
gcd=gcd(b,aModb)
EndIf
EndFunction
範例19-1F 以遞迴法作快速排序法。
(請看範例9-5-8)
範例19-1G 以非遞迴法自己安排堆疊重作以上範例。
目 的
使讀者了解編譯器須為遞迴處理那些工作。
輸出結果
筆者將程式執行過程及堆疊元素列印如下:
輸出說明
Pass1
1、50這筆資料達定點,也就是50之前的資料都比50小,50之後的資料都比50大。
2、將陣列的後段第14個元素(77)至第20個元素(99)進堆疊。
Pass2
1、將陣列前段元素第1個元素(34)至第13個元素(15)呼叫qsort進行排序。
2、34這筆資料達定點。
3、將陣列元素11至12之間加入堆疊。
程式列印
Rem19_1G
PrivateSubcmd_Click()
Statica(20)AsInteger
Staticb(100,2)AsInteger
StaticmAsInteger
StaticnAsInteger
StatickAsInteger
Staticg,jAsInteger
a
(1)=50:
a
(2)=99:
a(3)=32:
a(4)=76:
a(5)=16
a(6)=43:
a(7)=71:
a(8)=13:
a(9)=45:
a(10)=11
a(11)=23:
a(12)=15:
a(13)=66:
a(14)=77:
a(15)=34
a(16)=18:
a(17)=91:
a(18)=21:
a(19)=81:
a(20)=19
Fori=1To20
Debug.PrintRight(Str(a(i)),3);
Nexti
m=1:
n=20
a2:
Callqsort(a(),m,n,j)
Ifn-j>1Then
pushb(),k,j,m,n
EndIf
Debug.Print"堆疊元素";
printstackb(),k
m=m:
n=j-1
Ifn>mThen
GoToa2
EndIf
popb(),k,m,n
Ifk<>-1Then
GoToa2
EndIf
Fori=1To20
lst.AddItemStr(a(i))
Nexti
EndSub
PrivateSubpop(b()AsInteger,k,m,n)
Ifk=0Then
k=-1
ExitSub
EndIf
m=b(k,1):
n=b(k,2)
k=k-1
EndSub
PrivateSubprintdata(a()AsInteger)
StaticiAsInteger
Fori=1To20
Debug.PrintRight(Str(a(i)),3);
Nexti
Debug.Print
EndSub
PrivateSubprintstack(b()AsInteger,k)
StaticiAsInteger
Fori=1Tok
Debug.Printb(i,1);b(i,2);
Nexti
Debug.Print
EndSub
PrivateSubpush(b()AsInteger,k,j,m,n)
k=k+1
b(k,1)=j+1:
b(k,2)=n
EndSub
PrivateStaticSubqsort(a()AsInteger,mAsInteger,nAsInteger,jAsInteger)
StaticiAsInteger
StaticgAsInteger
g=g+1
Debug.Print:
Debug.Print"Pass:
";g
Debug.Print"排序";a(m);"至";a(n)
Ifm>=nThen
j=n
ExitSub
EndIf
i=m:
j=n+1
a1:
Do
i=i+1
LoopUntila(i)>=a(m)Ori>=n
Do
j=j-1
LoopUntila(j)<=a(m)Orj<=m
Ifi swapa(i),a(j) printdataa() GoToa1 EndIf swapa(m),a(j) printdataa() EndSub PrivateSubswap(qAsInteger,wAsInteger) StaticdAsInteger d=q: q=w: w=d EndSub 程式說明 1、將達定點元素以後的元素放進堆疊;k為堆疊個數,j為達定點之足標,m為左足標,n為右足標,b陣列存放堆疊元素。 2、前半段繼續呼叫排序副程式。 3、將堆疊部份取出。 4、k如果等於-1,表示堆疊已無元素,排序已完成此時可印出排序結果。 19-2 數值分析範例 19-2-1 割線法 設有一元多次方程式f(x)=anxn+an-1xn-1+...+a1x+a0試利用割線法(Secant)解方程式,其演算法如下: 1.任意於x軸上取2點x0及x1。 2.作(x0,f(x0))及(x1,f(x1))之割線,設交x軸於x2。 3.假如|x0-x1|<0.001則x0即為所求,否則x0用x1代入,x1用x2代入重覆步驟2與3。 範例19-2-1 將以上割線法程式化。 輸出結果 以下是n=3f(x)=x3-10.1x2+7.48x1+52.02=0之解。 程式列印 Rem19_2_1 DimmAsInteger PrivateSubcmdend_Click() End EndSub PrivateSubcmdstart_Click() Dimx(10)AsSingle Fori=0Tom x(i)=Val(txt(i).Text) Nexti Fori=-100To100 y0=0 y1=0 j=i+1 Fork=mTo0Step-1 y0=y0+x(k)*i^k y1=y1+x(k)*j^k Nextk '使用勘根法求得x0,x1 Ify0*y1<0Then n=n+1 s=Int(secant(x(),m,i,j)*100)/100 txtout.Text=txtout.Text&"x"&n&"="&s&"" EndIf Nexti EndSub PrivateSubForm_Load() m=Val(InputBox("","請輸入方程式冪次","3")) frm.Caption="請從最高次輸入方程式係數" Fori=1Tom Loadtxt(i): Loadlbl(i) hig=txt(0).Height*i txt(i).Movetxt(0).Left,txt(0).Top-hig lbl(i).Movelbl(0).Left,lbl(0).Top-hig txt(i).Visible=True lbl(i).Caption="x^"&i lbl(i).Visible=True Nexti txt(3).Text=1 txt (2).Text=-10.1 txt (1).Text=7.48 txt(0).Text=52.02 EndSub PublicFunctionsecant(x()AsSingle,m,x0,x1) Dimy1,x2AsSingle y0=0 y1=0 Fori=mTo0Step-1 y0=y0+x(i)*x0^i y1=y1+x(i)*x1^i Nexti x2=(x0-x1)*y0/(y1-y0)+x0 t=Abs(x2-x1) Ift<0.0001Then secant=x0 ExitFunction Else secant=secant(x(),m,x1,x2) EndIf EndFunction 19-2-2 牛頓除差法 設有一個一元多次方程式f(x)=anxn+an-1xn-1+...+a1x+a0,若已知其n點如下: x0,f(x1) x2,f(x2) : : xn,f(xn) 若欲求任意點的f(x)函數值,可用牛頓除差法(Newtondivided-difference)來解,其演算法如下: 1.將x0,x1...xn按照與x的距離由小而大從新排得x0,x1...xn。 2.f(x)=f(x0) +(x-x0)f[x0,x1] +(x-x0)(x-x1)f[x0,x1,x2] + +(x-x0)(x-x1)...(x-xn-1)f[x0,x1...xn-1] +(x-x0)(x-x1)...(x-xn)f[x0,x1...xn] 3.f[x0,x1,x2...xk]定義如下: f[x1,x2,...,xk]-f[x0,x1,x2,...,xk-1] =--------------------------------------- xk-x0 且可重覆分解,如下: f[x1,x2]-f[x0,x1] f[x0,x1,x2]=------------------- x2-x0 直到 f(x1)-f(x0) f[x0,x1]=---------------- x1-x0 範例19-2-2 將以上牛頓除差法程式化 使用物件 1.文書盒,用於存放x0,x1...,並將其值載入x()陣列。 Nametxtx()(動態文書盒) 2.文書盒,用於存放f(x0).f(x1)...,並將其值載入y()陣列 Nametxty() 3.文書盒,用於存放輸出結果。 Nametxt 4.功能按鈕。 Namecmdstart Caption開始 5.功能按鈕。 Namecmdend Caption結束 輸出結果 以下是筆者預設已知點數為4的輸出結果。 程式列印 Rem19_2_2 DimkAsInteger PrivateSubcmdend_Click() End EndSub PrivateSubcmdstart_Click() Dimx(20)AsSingle Dimy(20)AsSingle Dimc(20)AsSingle Fori=0Tok-1 x(i)=txtx(i) y(i)=txty(i) Nexti z=2.5 Fori=0Tok-1 c(i)=Abs(z-x(i)) Nexti '將x0,x1-------xn依照與X的距離由小而大排列 Fori=0Tok-2 Forj=0Tok-2-i Ifc(j)>c(j+1)Then swapc(j),c(j+1) swapx(j),x(j+1) swapy(j),y(j+1) EndIf Nextj Nexti txt.Text="f("&z&")="&sum(x(),y(),z,k-1) EndSub PublicSubswap(a,b) t=a: a=b: b=t EndSub '將f(x)分解成sum(n)+sum(n-1)+......+sum (1)+sum(0) 'sum(0)=y(0) 'b1副程式處理(x-x0)(x-x1)-----(x-xn) 'b2副程式處理f[x0,x1,------xn] PublicFunctionsum(x()AsSingle,y()AsSingle,z,n) Ifn<=0Then sum=y(0) ExitFunction Else sum=b1(x(),y(),z,n-1)*b2(x(),y(),n,n+1)+sum(x(),y(),z,n-1) 'b1中的z為未知x,n-1為未知足標 'b2中的n為f[x0,x1----xn]中xi的最高足標 'n1為xi的點數 EndIf EndFunction PublicFunctionb2(x()AsSingle,y()AsSingle,n,l) Ifl<=2Then b2=(y(n)-y(n-1))/(x(n)-x(n-1)) ExitFunction Else b2=(b2(x(),y(),n,l-1)-b2(x(),y(),n-1,l-1))/(x(n)-x(n-l+1)) EndIf EndFunction PublicFunctionb1(x()AsSingle,y()AsSingle,z,n) Ifn<=0Then b1=z-x(0) ExitFunction Else b1=(z-x(n))*b1(x(),y(),z,n-1) EndIf EndFunction PrivateSubForm_Load() k=Val(InputBox("","請輸入欲輸入點數","4")) Fori=1Tok-1 Loadtxtx(i): Loadtxty(i) hig=txtx(0).Height*i txtx(i).Movetxtx(0).Left,txtx(0).Top+hig txty(i).Movetxty(0).Left,txty(0).Top+hig txtx(i).Visible=True: txty(i).Visible=True Nexti txtx(0)=1: txty(0)=96 txtx (1)=1.5: txty (1)=90 txtx (2)=2: txty (2)=83 txtx(3)=3: txty(3)=67 EndSub
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第十 数值 分析