《新編MATLAB自學一本通》課件第4章 Matlab程序設計_第1頁
《新編MATLAB自學一本通》課件第4章 Matlab程序設計_第2頁
《新編MATLAB自學一本通》課件第4章 Matlab程序設計_第3頁
《新編MATLAB自學一本通》課件第4章 Matlab程序設計_第4頁
《新編MATLAB自學一本通》課件第4章 Matlab程序設計_第5頁
已閱讀5頁,還剩47頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

2025/4/30主要內容

M文件——腳本文件和函數文件

MATLAB程序流程控制與調試程序流程控制示例

匿名函數、子函數與嵌套函數

匿名函數、子函數與嵌套函數應用案例

編寫高效的MATLAB程序

養(yǎng)成良好的編程風格

2025/4/30第一節(jié)M文件——腳本文件和函數文件

2025/4/30一、腳本文件1.什么時候適合用腳本文件2.什么是腳本文件

指令的增加并且需要頻繁重復計算時,直接從指令窗進行計算很麻煩。這時候使用腳本文件最為適宜

所謂腳本文件,就是一些按用戶意圖排列的MATLAB指令(包括流程控制指令在內)組成的M文件。3.腳本文件和函數文件的區(qū)別

腳本文件運行后,產生的所有變量都駐留在MATLAB基本工作空間(baseworkspace)中。只要用戶不使用clear指令加以清除,或MATLAB不關閉,這些變量將一直保存在基本工作空間。2025/4/30二、函數文件其中out1,out2,…為輸出參數列表,in1,in2,…為輸入參數列表,funname為函數名。輸入參數和輸出參數個數根據問題的需要可以為0個到多個。函數文件也需要保存到MATLAB的搜索路徑下才能被調用。

格式:每個函數都由“function”引導,如下:function[out1,out2,…]=funname(in1,in2,…)注釋說明部分(%號引導的行)函數體

2025/4/30第二節(jié)MATLAB程序流程控制與調試

2025/4/30一、MATLAB程序流程控制if-else-end結構switch-case-otherwise-end結構for循環(huán)while循環(huán)try-catch結構其他中斷、暫停語句2025/4/30二、MATLAB程序調試

2.設置斷點進行調試

1.語法錯誤和運行結果錯誤

語法錯誤即所書寫的代碼不符合MATLAB語法規(guī)范所造成的錯誤,比如由于粗心造成的拼寫錯誤,不十分了解某個函數的調用方法而造成的調用錯誤等

。運行結果錯誤是一類非常難以檢查的錯誤,程序能正常運行,只是運行結果與期望的不一樣,這類錯誤大多是由于算法錯誤引起的。2025/4/30在程序編輯窗口中編寫的M代碼的每一行的前面都標有行號,在可執(zhí)行的命令行的行號后面都有一個小短橫“-”,單擊某一行的“-”,就可在該行設置一個斷點,此時的“-”變成了紅色的圓點,表示設置斷點成功。將光標放到M代碼的某一行上,然后按快捷鍵F12,或者單擊程序編輯窗口工具欄上的圖標,也可以通過菜單項“Debug→Set/ClearBreakpoint”設置斷點。用函數dbstop設置斷點。2025/4/30第三節(jié)程序流程控制示例

2025/4/30一、概述

要通過一個完整的MATLAB程序來展示各種流程控制的用法,該程序來源于如下一個有趣的問題。一只失明的小貓不幸掉進山洞里,山洞有三個門,其中第一個門進去后走兩個小時后可以回到地面,第二個門進去后走四個小時又回到原始出發(fā)點,不幸的是第三個門進去后走六個小時還是回到原始出發(fā)點。小貓由于眼睛失明,每次都是隨機的選擇其中一個門走。問題是這只可憐的小貓走出山洞的期望時間是多少?2025/4/30二、問題分析

設小貓走出山洞的期望時間為t,如果小貓不幸進了第二個或第三個門,那么它過四個小時或是六個小時后又和進門之前面臨狀況一樣了,只不過這兩種不幸的情況發(fā)生的概率都為1/3,而萬幸一次性走出去的概率也是1/3。于是我們可以得到下面的方程:

t=2*1/3+(4+t)*1/3+(6+t)*1/3

很簡單的一元一次方程,解得t=12。1.解析分析方法2.計算機模擬的思路2025/4/30輸入正整數n作為模擬小貓出洞的次數,生成一個1*n的數組T用來記錄每次小貓出洞時間,初始值為0。k從1循環(huán)到n,T(k)用來記錄每次實際出洞的時間。隨機等概率的生成{1,2,3}之間的一個數c,如果c=1,T(k)=T(k)+2,小貓走出山洞,開始下一次模擬。否則根據c=2或者c=3決定T(k)=T(k)+4或T(k)=T(k)+6,并繼續(xù)隨機生成c,直到c=1。模擬完n次后,計算T的均值得到小貓走出山洞的期望時間的近似值2025/4/30三、程序代碼

functionT=cat_in_holl(varargin)%varargin,使函數可以接受參數個數不定的輸入if~isempty(varargin)%輸入參數非空n=varargin{1};%varargin為cell型數組,取其第一個元素賦給nend%try-catch結構用法示例try%如果n是正整數下面語句不會發(fā)生錯誤,進而執(zhí)行try-catch結構之后的語句

%否則會發(fā)生錯誤,執(zhí)行由catch引導的語句。

ifn>0&&mod(n,1)==0;%n為正整數的判斷條件

%空語句,不會報錯

else%n不是正整數,報錯

error;end2025/4/30catchME%ME,用來記錄發(fā)生錯誤的一些信息

disp('函數沒有輸入參數或者輸入參數不是正整數標量');T=[];%給T賦空值

return;%函數返回,后面語句不再執(zhí)行,沒有return會接著執(zhí)行后面的語句end%switch-case-end結構用法示例switchnargin%nargin,函數輸入參數的個數

case1%case1的情況是我們程序的核心部分,即整個模擬出洞的過程

T=zeros(1,n);fork=1:n%for循環(huán)用法示例

c=unidrnd(3,1);%等概率隨機生成{1,2,3}中某個數字2025/4/30whilec~=1%while循環(huán)用法示例

ifc==2T(k)=T(k)+4;elseT(k)=T(k)+6;endc=unidrnd(3,1);endT(k)=T(k)+2;endcase2T=[];disp('函數只能有一個輸入參數,且為正整數');otherwiseT=[];disp('函數輸入參數個數不能大于1,參數需為正整數');end2025/4/30四、程序驗證

在Editor中新建一個m文件,將上述程序復制過去,并以cat_in_holl.m文件名保存到MATLAB的搜索路徑下,對于n=10^4以及n=10^5,我們可以用如下指令得到近似期望時間T:

>>n=1e4; >>T=cat_in_holl(n); >>mean(T) ans= 11.8888 >>T=cat_in_holl(n); >>mean(T) ans= 12.02222025/4/30cat_in_holl.m是一個完整的m函數文件,里面用到了幾乎各種流程控制方法。讀者朋友可以試運行如下指令,觀看程序結果,體會各流程控制的功能:

T=cat_in_holl;%沒有輸入參數

T=cat_in_holl(10.1);%輸入參數為小數

T=cat_in_holl(-10000);%輸入參數為負數

T=cat_in_holl({1000});%輸入為元胞數組

T=cat_in_holl(1000,100);%輸入參數為2個

T=cat_in_holl(1000,100,100);%輸入參數大于2個2025/4/30第四節(jié)匿名函數、子函數與嵌套函數

2025/4/30一、匿名函數1. 匿名函數定義

fhandle=@(arglist)expr

其中,expr是具體的函數表達式,arglist是指定的函數的自變量。 匿名函數按照不同的分類方法可以分為不同的種類。按照自變量的個數以及層數可以分為以下幾種:單變量匿名函數,多變量匿名函數,單重匿名函數,多重匿名函數。2. 單變量匿名函數

f=@(x)x.^2;3. 多變量匿名函數

g=@(x,y)x.^2+y.^2;2025/4/304. 單重匿名函數 無論單變量還是多變量匿名函數,都屬于單重匿名函數。這類匿名函數的特點是,只有一個“@”符號引導,“@”之后就是具體的函數表達式。自變量輸入單重匿名函數后,得到的是具體的數值。除了單重匿名函數外,還有雙層、乃至多重匿名函數。這些多重匿名函數在參數傳遞方面非常方便。5. 多重匿名函數

f=@(a,b)@(x)a*x+b f= @(a,b)@(x)a*x+b

其中“a,b”是外層變量,“x”是內層變量。可以這樣理解這個表達式:每個“@”符號后面括號里的變量的作用域一直到表達式的結尾。這樣,“a,b”的作用域就是“@(x)a*x+b”,而“x”的作用域就是“a*x+b”。因此,對于給定的“a,b”,“gab=f(a,b)”是一個單層以x為變量的單變量匿名函數。2025/4/30二、子函數函數M文件中,我們稱第一個“function”引導的函數為主函數,外部調用函數文件時總是從主函數開始執(zhí)行。如果整個函數文件只有一個函數,那這個函數就是主函數。在設計比較復雜的程序的時候,為了能夠使程序之間邏輯關系清楚,易于閱讀和維護,通常會采用模塊化的設計方式,這時就會涉及子函數的使用。從函數編寫格式以及形態(tài)上來說,子函數和主函數并無區(qū)別,區(qū)別僅在于在函數文件中的位置以及調用關系。2025/4/30子函數是在同一函數文件中,主函數之后的由“function”引導的函數,一個函數文件可以有多個子函數。這些子函數在函數文件中的排列順序可以隨意,前提是都要位于主函數后。子函數可以被其所在的函數文件中的主函數和其他子函數調用,子函數也可以調用主函數,在設計子函數調用主函數的程序時一定要小心,避免形成“死”的調用循環(huán)。

2025/4/30三、嵌套函數在程序編寫中,有的數學表達式比較長,不方便用一行來表示,而且這個表達式里還有其他的參數。這時候我們就需要將其寫成函數,用嵌套函數可以方便的解決參數共享問題。當求解微分方程或者進行優(yōu)化問題求解時,一些復雜的表達式往往涉及參數傳遞過程,這個時候,比較適合將其表達式寫成嵌套函數。在編寫GUI用戶界面的回調函數時,參數傳遞往往是個棘手的問題。利用嵌套函數,可以方便解決這個問題。2025/4/301. 嵌套函數定義

嵌套函數,即nestedfunction,顧名思義,是嵌套在函數體內部的函數。嵌套函數以function聲明,結束的時候加上end。需要說明的是,包含有嵌套函數的函數,無論他是主函數、子函數或者嵌套函數,都應該在末尾的地方加上end。下面代碼是一個簡單的嵌套函數的例子:functionr=MyTestNestedFun(input)a=5;c=sin(input)+tan(input);functiony=nestedfun(b)y=a*c+b;endr=nestedfun(5);end

2025/4/302. 嵌套函數種類嵌套函數可以分為單重嵌套函數和多重嵌套函數。單重嵌套函數,這樣的函數嵌套在別的函數體內,自己內部不再有嵌套的函數,例如上面介紹的是單重嵌套函數。多重嵌套函數嵌套在別的函數體內,同時自己內部又嵌套著別的另一層或幾層函數。如下面類型的函數:2025/4/30functionx=A(p1,p2)...functiony1=B1(p3)...functionz1=C1(p4)...end...end...functiony2=B2(p5)...functionz2=C2(p6)...functionw=D(p7)...endendendend

2025/4/303. 嵌套函數的變量作用域變量的作用域指的變量能夠被程序訪問、修改、設置等的代碼范圍。

父函數和嵌套在其內的函數,他們各自的變量是可以互相訪問的。但是必須注意的是,嵌套函數訪問父函數的變量,可以在函數定義里直接拿過來用,而父函數訪問嵌套在其內的函數里的變量則必須要經過調用之后。彼此沒有嵌套關系的嵌套函數間是不能簡單得共享變量的。如果非要共享,則只能通過它們所在的父函數來進行。2025/4/30四、嵌套函數彼此調用關系將主函數看成“父親”,嵌套函數依據嵌套深度可以看成“兒子”,“孫子”,“重孫”等等。這樣最外層的主函數可以認為是所有內部函數的“祖先”,位于不同嵌套函數里的函數之間的關系類似于一個家族之間的“親屬關系”。嵌套函數之間的調用關系可以總結成下面幾句話:父親可以求助兒子,兒子可以求助父親,也即父子可以互相求助。一個人不能求助孫子、重孫等后代,但是可以求助自己的直系祖宗(祖父、曾祖父等等)以及和其直系祖宗是親兄弟的先人。一個人可以求助自己的親兄弟,或者親叔叔、親伯伯但不能求助侄兒。

2025/4/30第五節(jié)匿名函數、子函數與嵌套函數應用案例2025/4/30一、匿名函數應用實例1. 匿名函數在求解方程中的應用【例4.5-1】求下列方程的根:求解代碼如下:>>f=@(x)exp(x)+x^2+x^(sqrt(x))-100%構造方程的匿名函數形式f=@(x)exp(x)+x^2+x^(sqrt(x))-100>>formatlong>>x0=fzero(f,3)%求方程的根,初始值為3x0=4.163549956946139%求出的解>>f(x0)%代入原方程驗證ans=2.842170943040401e-0142025/4/30一、匿名函數應用實例【例4.5-1序】對于 ,求下列方程相應的值,并畫出和相應的的圖像。

求解代碼如下:f=@(a)@(x)exp(x)+x^a+x^(sqrt(x))-100;%構造函數句柄formatlongaa=0:0.01:2;plot(aa,arrayfun(@(a)fzero(f(a),4),aa),'*-')%利用arrayfun求解不同的a對應的xxlabel('$a$','interpreter','latex','fontsize',15)%標注x、y坐標軸,按照latex語法ylabel('$x$','interpreter','latex','fontsize',15)title('$\mathrm{e}^{x}+x^{\sqrt{x}}+x^a-100$','interpreter','latex',...'fontsize',15)

2025/4/30【例4.5-1序】得到的圖形2025/4/30一、匿名函數應用實例2. 匿名函數在顯式表示隱函數方面的應用 隱函數一般無法在數學上顯式的表達。這里說的顯式表示指的是構造一個MATLAB函數來表達隱函數,具體思路是對于給定的隱函數的自變量x,通過數值方法求解出因變量y,這樣就相當于顯式表達隱函數。請看下面的例子:

【例4.5-2】顯式表示下列y關于x的隱函數: 利用匿名函數,我們可以在MATLAB中顯式得寫出y和x的關系式如下:

y=@(x)fzero(@(y)(exp(y)+x^y)^(1/y)-x^2*y,1);2025/4/30一、匿名函數應用實例 【例4.5-3】顯式表示下列z關于x,y的隱函數:

z=@(x,y)fzero(@(z)z-sin((z*x-0.5)^2+x*2*y^2-z/10)*...exp(-((x-0.5-exp(-y+z))^2+y^2-z/5+3)),rand);z(1,2)ans=7.369600885222808e-004z(0,0.5)ans=0.0028075073342922025/4/30一、匿名函數應用實例3. 匿名函數在求積分區(qū)域方面的應用

有的時候,我們需要根據已知的積分值和被積函數求對應的積分區(qū)域,當被積函數表達式不是很復雜的時候,用匿名函數比較適合。請看下例:

【例4.5-4】要使sin(x)^2./(x^2)這個式子的積分值為0.99*pi,求其關于0對稱的積分區(qū)域。

u0=fzero(@(u)0.99*pi/2-quadl(@(x)sin(x).^2./(x.^2),0,u),1) u0= 32.3138103582174102025/4/30一、匿名函數應用實例4. 匿名函數和符號計算的結合

【例4.5-5】求下面函數三階導數在[0,1]區(qū)間的圖像:

本例如果用手算的話,比較繁瑣。如果用符號運算得到三階導數的解析表達式,然后再轉化成匿名函數,則比較方便。本例展示了符號計算和數值計算結算結合的一種途徑。代碼如下:symsxf=(x+tan(x))^(sin(x));c=diff(f,3);f3=eval(['@(x)'vectorize(c)]);x=linspace(0,1,100);plot(x,f3(x))title('(x+tan(x))\^(sin(x))三階導數圖像')2025/4/302025/4/30一、匿名函數應用實例5. 匿名函數在優(yōu)化中的應用 匿名函數在優(yōu)化中的應用主要是以表示目標函數的形式出現的。

【例4.5-6】求下面函數的最小值 用匿名函數來表示目標函數如下:

f=@(x)3*x(1)^2+2*x(1)*x(2)+x(2)^2;

進一步求解:

x0=[1,1];%初始值

[x,fval]=fminunc(f,x0) x= 1.0e-006* 0.2541-0.2029 fval= 1.3173e-0132025/4/30二、子函數和嵌套函數應用實例在求解積分上限中的應用【例4.5-7】如下述積分表達式,如何已知和,求得?2025/4/30functionsol=exampleIntLimit1(a,e,l)%用嵌套函數表示被積表達式

functionf=fun1(beta)f=a.*(1-e.^2)./(1-e.^2.*sin(beta).^2).^(3/2);end%調用fzero求滿足條件的beta0值sol=fzero(@(beta0)fun2(beta0,l,@fun1),3);end%用子函數表示積分functiong=fun2(beta0,l,fhdle)g=quadl(fhdle,0,beta0)-l;end2025/4/30二、子函數和嵌套函數應用實例2. 在GUI中的應用(三角界面,見書中代碼)在3D作圖中的應用【例4.5-9】畫出下列函數的圖像:其中2025/4/30function[m,n,TT]=plot3dnmT(N,L)%N:inf的近似,L:[0,2]區(qū)間的剖分個數C=zeros(N,1);%nested-function:Tmn=calcT(mm,nn)中用來存儲計算結果m=linspace(0,2,L);[m,n]=meshgrid(m,m);TT=zeros(size(n));%和網格數據m,n對應的計算出來的T(m,n)網格數據forii=1:Lforjj=1:LTT(ii,jj)=calcT(m(ii,jj),n(ii,jj));endend%=====計算T(m,n)的nest-functionfunctionTmn=calcT(mm,nn)forN1=1:NC(N1)=(mm^N1/gamma(N1+1))*sum(nn.^(0:N1-1)./gamma(1:N1));Tmn=1.0-exp(-mm-nn)*sum(C);endendmesh(n,m,TT);end

2025/4/30嵌套函數表示待優(yōu)化的目標函數【例4.5-10】已知求下面表達式的最小值。其中,m在[0,2]這個區(qū)間范圍內

2025/4/30functionm=Findmw=[pi/2,pi,pi*1.5];N=[pi/2-1,-2,-1.5*pi-1];functiony=ObjecFun(m)y=(quadl(@(t)t.^m.*cos(t),0,w(1))-N(1))^2+(quadl(@(t)t.^m.*cos(t),0,...w(2))-N(2))^2+(quadl(@(t)t.^m.*cos(t),0,w(3))-N(3))^2;endm=fminbnd(@ObjecFun,0,2);end2025/4/30二、子函數和嵌套函數應用實例5. 嵌套函數在表示微分方程方面的應用(求解微分方程,見書中代碼)2025/4/30第六節(jié)編寫高效的MATLAB程序2025/4/30一、重新認識循環(huán)1. 高版本MATLAB對循環(huán)結構的優(yōu)化

從MATLAB6.5版開始,MATLAB引入了JIT(justintime)技術和加速器(accelerator),并在后續(xù)版本中不斷優(yōu)化。到了R2009a,很多情況下,循環(huán)體本身已經不是程序性能提高的瓶頸了,瓶頸更多的來源于循環(huán)體內部的代碼實現方式,以及使用循環(huán)的方式。(詳見例【例4.6-1】)選擇循環(huán)還是向量化凡是涉及到矩陣運算的時候,則盡量用向量化如果向量化可能導致超大型矩陣的產生,使用前要慎重向量化的使用要靈活,多分析其運行機制,并與循環(huán)做對比MATLAB初學者要盡量多用向量化思路編程高效的編程包括高效的開發(fā)和高效的運行

2025/4/30二、提高代碼效率的方法

1. 預分配內存 當矩陣尺寸較大時,預分配內存(preallocation),是MATLAB高效編程中最應該注意,同時也是很容易把握的一個技巧(詳見例【例4.6-5】)選用恰當的函數類型

MATLAB有多種函數類型,不同的函數類型調用效率差別相當大,為了寫出高效的MATLAB代碼,我們就要選用恰當的函數類型來實現我們的任務。(詳見例【例4.6-6】【例4.6-7】)選用恰當的數據類型

MATLAB同樣有多種數據類型,不同的數據類型在存儲和訪問效率上也不盡相同,選用恰當的數據類型對寫出高效的MATLAB代碼同樣具有重要的意義。(詳見例【例4.6-8】)2025/4/30二、提高代碼效率的方法

4. 減少減少無謂損耗——給一些函數“瘦身”

MATLAB自身以及工具箱里的很多函數具有較廣的通用性,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論