版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第四章MATLAB編程基礎(chǔ)4.1概述4.2腳本文件4.3流程控制4.4函數(shù)文件4.5M文件調(diào)試4.6M文件性能分析4.7本章小結(jié)4.1概述MATLAB提供了完整的編寫應(yīng)用程序的能力,這種能力通過一種被稱為M語言的高級語言來實現(xiàn)。這種編程語言是一種解釋性語言,利用該語言編寫的代碼僅能被MATLAB接受,被MATLAB解釋、執(zhí)行。其實,一個M語言文件就是由若干MATLAB的命令組合在一起構(gòu)成的,這些命令都是在前面章節(jié)中介紹的合法的MATLAB命令。和C語言類似,M語言文件都是標(biāo)準(zhǔn)的純文本格式的文件,其文件的擴展名為.m。
使用M文件最直接的好處就是可以將一組MATLAB命令組合起來,通過一個簡單的指令就可以執(zhí)行這些命令。這些命令可以完成某些MATLAB的操作,也可以實現(xiàn)某個具體的算法。其實,MATLAB產(chǎn)品族中包含的工具箱就是由世界上在相應(yīng)專業(yè)領(lǐng)域內(nèi)的頂尖高手,利用M語言開發(fā)的算法函數(shù)文件集合。讀者也可以結(jié)合自己工作的需要,為自己的MATLAB開發(fā)具體的算法和工具箱。
MATLAB的函數(shù)主要有兩類,一類被稱為內(nèi)建(Build-in)函數(shù),這類函數(shù)是由MATLAB的內(nèi)核提供的,能夠完成基本的運算,例如三角函數(shù)、矩陣運算的函數(shù)等。另外一類函數(shù)就是利用高級語言開發(fā)的函數(shù)文件,這里的函數(shù)文件既包括用C語言開發(fā)的MEX函數(shù)文件,又包含了M函數(shù)文件。有關(guān)MEX函數(shù)文件的內(nèi)容已經(jīng)超出了本書的內(nèi)容,將在《MATLAB外部編程接口》一書中詳細(xì)講述。
如前所述,MATLAB的M語言文件是純文本格式的文件,利用任何一種純文本編輯器都可以編寫相應(yīng)的文件,例如Windows平臺下的記事本、UltraEdit等軟件,或者Unix平臺下的Emacs軟件等。同樣,為了方便編輯M文件,MATLAB也提供了一個編輯器,叫作meditor,它也是系統(tǒng)默認(rèn)的M文件編輯器。運行meditor的方法非常簡單,在MATLAB命令行窗口中鍵入下面的指令就可以打開meditor:
>>edit
這時MATLAB將啟動meditor,然后創(chuàng)建一個未命名的空白文件,如圖4-1所示。圖4-1meditor的運行界面
這時用戶就可以直接在編輯器中鍵入MATLAB指令,開發(fā)M語言文件了。此外,運行meditor還可以通過“File”菜單中“New”子菜單下的“M-File”命令來實現(xiàn),或者直接單擊MATLAB用戶界面工具欄上的新建按鈕完成同樣的工作。
M語言文件可以分為兩類,其中一類是腳本文件,另外一類叫作函數(shù)文件。本章將分別介紹這兩類文件的編寫方法。4.2腳本文件
腳本文件是最簡單的一種M語言文件,在本章前面章節(jié)的例子中都使用了腳本文件。所謂腳本文件,就是由一系列的MATLAB指令和命令組成的純文本格式的M文件,執(zhí)行腳本文件時,文件中的指令或者命令按照出現(xiàn)在腳本文件中的順序依次執(zhí)行。腳本文件沒有輸入?yún)?shù),也沒有輸出參數(shù),執(zhí)行起來就像早期的DOS操作系統(tǒng)的批處理文件一樣,而腳本文件處理的數(shù)據(jù)或者變量必須在MATLAB的公共工作空間中。[例子4-1]
腳本文件示例。001 %注釋行002 %M腳本文件示例003 %"flowerpetal"004 %以下為代碼行005 %計算006 theta=-pi:0.01:pi;007 rho(1,:)=2*sin(5*theta).^2;008 rho(2,:)=cos(10*theta).^3;009 rho(3,:)=sin(theta).^2;010 rho(4,:)=5*cos(3.5*theta).^3;011 fork=1:4012 %圖形輸出013 subplot(2,2,k)014 polar(theta,rho(k,:))015 end016 disp('程序運行結(jié)束!')在MATLAB命令行中運行該腳本文件:>>script_example程序運行結(jié)束!圖4-2例子4-1腳本文件的運行結(jié)果
仔細(xì)察看例子4-1的腳本文件,在腳本文件中,主要由注釋行和代碼行組成。M文件的注釋行需要使用%定義符,在%之后的所有文本都認(rèn)為是注釋文本,不過,M文件的注釋定義符僅能影響一行代碼,類似于C++語言中的“//”。然而在M語言中,沒有類似C語言的注釋定義符“/*”和“*/”,所以無法一次定義多行注釋。給程序添加適當(dāng)?shù)淖⑨屖橇己玫木幊塘?xí)慣,希望讀者能夠在日常編程中多多使用。
腳本文件中的代碼行都是一些簡單的MATLAB指令或者命令,這些命令可以用來完成相應(yīng)的計算處理數(shù)據(jù)、繪制圖形結(jié)果的操作,也可以在腳本文件中調(diào)用其他的函數(shù)完成復(fù)雜的數(shù)學(xué)運算,在例子4-1中就完成了這些工作。另外,在MATLAB中還有一些指令用來處理程序和用戶之間的交互,在表4-1中進(jìn)行了總結(jié)。表4-1腳本文件中常用的MATLAB指令MATLAB一般使用腳本文件作為某種批處理文件,其中,有兩個批處理文件經(jīng)常被MATLAB自動調(diào)用,這兩個腳本文件分別為startup.m和finish.m。
startup.m文件在MATLAB啟動時自動被執(zhí)行,用戶可以自己創(chuàng)建并定義編寫該文件,例如在文件中添加物理常量的定義、系統(tǒng)變量的設(shè)置或者M(jìn)ATLAB搜索路徑的設(shè)置。當(dāng)用戶安裝MATLAB之后,在<MATLABROOT>\toolbox\local路徑下有一個M文件,名為Starupsav.m,該文件可以看作是startup.m文件的模板,可以修改該文件,然后將其以文件名startup.m的形式保存在<MATLABROOT>\toolbox\local路徑下。
與startup.m文件相對應(yīng)的是finish.m文件,該文件在MATLAB退出時自動執(zhí)行,用戶可以自己創(chuàng)建并定義編寫該文件,例如在文件中添加保存數(shù)據(jù)等指令,這樣可以將每次退出前的工作結(jié)果進(jìn)行保留。同樣,在<MATLABROOT>\toolbox\local路徑下有兩個文件,分別為finishsav.m和finishdlg.m,這兩個文件可以用來作為finish.m文件的模板,相關(guān)的具體內(nèi)容介紹請讀者自己察看相應(yīng)的文件和幫助文檔。4.3流程控制4.3.1選擇結(jié)構(gòu)如前所述,當(dāng)人們判斷某一條件是否滿足,根據(jù)判斷的結(jié)果來選擇不同的解決問題的方法時,就需要使用選擇結(jié)構(gòu)。和C語言類似,MATLAB的條件判斷可以使用if語句或者switch語句。1.if語句if語句的基本語法結(jié)構(gòu)有三種,分別如下:(1)if(關(guān)系運算表達(dá)式) MATLAB語句end
這種形式的選擇結(jié)構(gòu)表示,當(dāng)關(guān)系運算表達(dá)式計算的結(jié)果為邏輯真的時候,執(zhí)行MATLAB語句,這里的MATLAB語句可以是一個MATLAB表達(dá)式,也可以是多個MATLAB表達(dá)式。在MATLAB語句的結(jié)尾處,必須有關(guān)鍵字end。if(關(guān)系運算表達(dá)式) MATLAB語句Aelse MATLAB語句Bend
這種選擇結(jié)構(gòu)表示,當(dāng)關(guān)系運算表達(dá)式的計算結(jié)果為邏輯真的時候,執(zhí)行MATLAB語句A,否則執(zhí)行MATLAB語句B,在語句B的結(jié)尾必須具有關(guān)鍵字end。if(關(guān)系運算表達(dá)式a) MATLAB語句Aelseif(關(guān)系運算表達(dá)式b) MATLAB語句Belse(關(guān)系運算表達(dá)式c)
end
這種選擇結(jié)構(gòu)可以判斷多條關(guān)系運算表達(dá)式的計算結(jié)果,然后按照執(zhí)行的邏輯關(guān)系執(zhí)行相應(yīng)的語句。讀者可以根據(jù)類似的C語言知識或者前面兩種選擇結(jié)構(gòu)的介紹判斷這種結(jié)構(gòu)的執(zhí)行方式?!璠例子4-2]if語句的使用——if_examp.m。讀者通過本例子將同時了解meditor的基本使用方法。打開meditor,然后鍵入下面的指令:001 clearall002003 I=1;004 J=2;005006 ifI==J007 A(I,J)=2;008 elseifabs(I-J)==1009 A(I,J)=?1;010 else011 A(I,J)=0;012 end
注意:在鍵入程序時,不要將行號(001~012)也敲進(jìn)去,在這里設(shè)置行號的主要目的是為了便于講解和分析程序。在MATLAB的M語言編輯器中進(jìn)行文本編輯時,編輯器的最左側(cè)就是當(dāng)前文件的行號,如圖4-3所示。
圖4-3編輯M語言時左側(cè)的文件行號
細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn),在M語言編輯器的最右側(cè)的一欄中有一些特殊色彩的標(biāo)識,默認(rèn)情況下(如圖4-1)該標(biāo)識(方塊)為綠色,而在圖4-3所示的編輯器中是桔黃色,同時在相應(yīng)的代碼下會有桔黃色的波浪線,這是新版MATLAB中M語言編輯器針對正在編輯的M文件進(jìn)行分析的結(jié)果,表示當(dāng)前的代碼可能存在一些潛在的錯誤,把鼠標(biāo)放置在桔黃色的方塊或者橫線上,可獲取相應(yīng)的警告信息。如果單擊桔黃色橫線,則M語言編輯器光標(biāo)會自動跳轉(zhuǎn)到出現(xiàn)問題的代碼處,如圖4-4所示。
圖4-4顯示的警告信息
運行例子4-2的方法和效果如下:>>if_exampA=0-1
例子4-2代碼的核心是006~012行的部分,這部分展示了if-elseif-else-end語句組合的使用方法。請讀者仔細(xì)察看,并且通過修改程序003和004行中對I和J的賦值來察看整個語句的執(zhí)行情況。和C語言類似,if-elseif-else的語句結(jié)構(gòu)也可以嵌套地使用,也就是可以存在這樣的語句結(jié)構(gòu):if(關(guān)系表達(dá)式a) if(關(guān)系表達(dá)式b)MATLAB語句A elseMATLAB語句B endelse if(關(guān)系表達(dá)式c)MATLAB語句C elseMATLAB語句D endend注意:在使用嵌套的選擇結(jié)構(gòu)時,需要小心if語句和end關(guān)鍵字的配對。[例子4-3]
嵌套使用的if結(jié)構(gòu)——if_examp2.m。001 clearall002 003 if1004 disp('Is1')005 else006 disp('Not1')007 end008009 I=1;010 ifI011 ifI<2012 disp('Iisbiggerthan0butlessthan2')013 end014 else015 ifI>-2016 dis('Iislessthan0butbiggerthan-2')017 end018 end該程序的運行方法和效果如下:>>if_examp2Is1Iisbiggerthan0butlessthan2
在例子4-3中,主要說明了嵌套的if結(jié)構(gòu)和在關(guān)系表達(dá)式中使用常量的方法。在代碼的003行,if語句的關(guān)系表達(dá)式為常數(shù)1,這個時候if語句將始終認(rèn)為非零值為邏輯真,所以,程序執(zhí)行了004行的代碼。同樣,在程序的009行,if語句的關(guān)系表達(dá)式為變量I,若I的數(shù)值為非零值,則if語句判斷其為邏輯真,所以,代碼的016行只有在I為0時,才可能被執(zhí)行。2.switch語句另外一種構(gòu)成選擇結(jié)構(gòu)的關(guān)鍵字就是switch。在處理實際問題的時候,往往要處理多個分支,這時如果使用if-else語句處理多分支結(jié)構(gòu)往往使程序變得十分冗長,從而降低了程序的可讀性。switch語句就可以用于處理這種多分支的選擇,它的基本語法結(jié)構(gòu)如下:switch(表達(dá)式) case常量表達(dá)式a:語句A case常量表達(dá)式b:語句B
case常量表達(dá)式m:語句M otherwise常量表達(dá)式n:語句Nend…
在switch語句之后的表達(dá)式可以是一個數(shù)值類型表達(dá)式或者是一個數(shù)值類型的變量,當(dāng)這個表達(dá)式的值同case后面的某一個常量表達(dá)式相等時,則執(zhí)行該case后面的常量表達(dá)式后面的語句。注意:
MATLAB的switch和C語言的switch語句結(jié)構(gòu)不同。在C語言中,每一個case后面的語句中必須包含類似break語句的流程控制語句,否則程序會依次執(zhí)行符合條件的case語句后面的每一個case分支。但是在MATLAB中就不必如此,程序僅僅執(zhí)行符合條件的case分支。例子4-4switch結(jié)構(gòu)使用示例——switch_examp.m。001 clearall002 003 algorithm=input('Enteranalgorithminquotes(ode23,ode15s,etc:)');004 005 switchalgorithm006 case'ode23'007 str='2nd/3rdorder';008 case{'ode15s','ode23s'}009 str='stiffsystem';010 otherwise011 str='otheralgorithm';012 end013 disp(str);該文件的運行方法和效果如下:>>switch_exampEnteranalgorithminquotes(ode23,ode15s,etc:)'ode23'2nd/3rdorder>>switch_exampEnteranalgorithminquotes(ode23,ode15s,etc:)'ode4'otheralgorithm
例子4-3中需要用戶在執(zhí)行程序的過程中輸入一個字符串,switch語句根據(jù)用戶的輸入判斷執(zhí)行相應(yīng)的case分支。若沒有符合條件的case分支,則switch執(zhí)行otherwise后面的語句。若switch結(jié)構(gòu)中沒有定義otherwise及其相應(yīng)的代碼,則程序不會進(jìn)行任何操作,而是直接退出switch結(jié)構(gòu)。提示:在處理以字符串變量或者常量參與的關(guān)系判斷操作時,使用switch結(jié)構(gòu)要比if-else結(jié)構(gòu)效率高一些。由于MATLAB的switch結(jié)構(gòu)沒有C語言的fall-through特性,所以,如果需要針對多個條件而使用同一個case分支的時候,需要使用元胞數(shù)組與之配合,參見例子4-4。[例子4-5]switch結(jié)構(gòu)使用示例——switch_examp2.m。001 clearall002003 var=input('InputaNumer:');004 switchvar005 case1006 disp('1')007 case{2,3,4}008 disp('2or3or4')009 case5010 disp('5')011 otherwise012 disp('somethingelse')013 end例子4-5運行的方法和效果如下:>>switch_examp2InputaNumer:11>>switch_examp2InputaNumer:32or3or4>>switch_examp2InputaNumer:7somethingelse
例子4-5代碼的核心部分為007行,這里使用元胞數(shù)組增加判斷條件的個數(shù),當(dāng)輸入的數(shù)字為2、3或者4時,switch結(jié)構(gòu)將使用同一個case分支進(jìn)行判斷、計算。注意:從代碼的完整性和可靠性角度出發(fā),在使用switch語句時,一定要包含otherwise分支,這是一種良好的編程習(xí)慣。4.3.2循環(huán)結(jié)構(gòu)在解決很多問題的時候需要使用循環(huán)結(jié)構(gòu),例如求解數(shù)列的和或者進(jìn)行某種迭代法求解數(shù)值方程時,都需要循環(huán)結(jié)構(gòu)配合完成計算。在MATLAB中,包含兩種循環(huán)結(jié)構(gòu),一種是循環(huán)次數(shù)不確定的while循環(huán),而另一種是循環(huán)次數(shù)確定的for循環(huán)。
1.while循環(huán)結(jié)構(gòu)while語句可以用來實現(xiàn)“當(dāng)”型的循環(huán)結(jié)構(gòu),它的一般形式如下:while(表達(dá)式)MATLAB語句end
當(dāng)表達(dá)式為真時,循環(huán)將執(zhí)行由語句構(gòu)成的循環(huán)體,其特點是先判斷循環(huán)條件,如果循環(huán)條件成立,即表達(dá)式運算結(jié)果為“真”,再執(zhí)行循環(huán)體。循環(huán)體執(zhí)行的語句可以是一句也可以是多句,在MATLAB語句之后必須使用關(guān)鍵字end作為整個循環(huán)結(jié)構(gòu)的結(jié)束。另外,在循環(huán)過程中一定要能夠改變關(guān)系表達(dá)式或者布爾類型變量的值,或者使用其他方法來跳出循環(huán),否則會陷入死循環(huán)(無法正常退出的循環(huán)叫作死循環(huán))。例子4-6
使用while語句求解 。001 i=1;002 sum=0;003 while(i<=1000)004 sum=sum+i;005 i=i+1;006 end007 str=['計算結(jié)果為:',num2str(sum)];008 disp(str)
例子4-6的運行結(jié)果為
>>while_example
計算結(jié)果為:500500
例子4-6的002~006行使用了while循環(huán)結(jié)構(gòu),在循環(huán)結(jié)構(gòu)中進(jìn)行了累加的操作。需要注意的是,在MATLAB中沒有類似C語言的++或者+=等運算操作符,因此在進(jìn)行諸如累加或者遞減的運算時,不得不給出完整的表達(dá)式。另外,例子4-6求數(shù)列和的算法的運算效率很低,在MATLAB中不要使用這樣的結(jié)構(gòu)完成類似的運算,而需要采用向量化的計算。
注意:
while循環(huán)結(jié)構(gòu)的關(guān)系表達(dá)式可以是某個數(shù)據(jù)變量或者常量,這時,將按照非零值為邏輯真進(jìn)行相應(yīng)的操作。另外,在進(jìn)行上述操作時,若數(shù)據(jù)變量為空矩陣,則while語句將空矩陣作為邏輯假處理,也就是說,在whileAMATLAB語句S1end結(jié)構(gòu)中,若A為空矩陣,則MATLAB語句S1永遠(yuǎn)不會被執(zhí)行。
2.for循環(huán)結(jié)構(gòu)使用for語句構(gòu)成循環(huán)是最靈活、簡便的方法,不過,使用for語句循環(huán)需要預(yù)先知道循環(huán)體執(zhí)行的次數(shù),所以這種循環(huán)一般叫作確定循環(huán)。在MATLAB中for循環(huán)的基本結(jié)構(gòu)如下:forindex=start:increment:end MATLAB語句end其中,index的取值取決于start和end的值,一般地,這里通常使用等差的數(shù)列向量,參見例子4-7。例子4-7
使用for語句求解 。001 sum=0;002 fori=1:1000003 sum=sum+i;004 end 005 str=['計算結(jié)果為:',num2str(sum)];006 disp(str)例子4-7運行的結(jié)果為>>for_example計算結(jié)果為:500500
在例子4-7中,002行的代碼使用了確定次數(shù)的for循環(huán)結(jié)構(gòu),循環(huán)次數(shù)使用行向量進(jìn)行控制,而且索引值i按照默認(rèn)的數(shù)值1進(jìn)行遞增。在for循環(huán)語句中,不僅可以使用行向量進(jìn)行循環(huán)迭代的處理,也可以使用矩陣作為循環(huán)次數(shù)的控制變量,這時循環(huán)的索引值將直接使用矩陣的每一列,循環(huán)的次數(shù)為矩陣的列數(shù),參見例子4-8。例子4-8for循環(huán)示例。001 A=rand(3,4);002003 fori=A004 sum=mean(i)005 end例子4-8運行的結(jié)果為:>>for_matricessum=0.2728sum=0.6649sum=0.4275sum=0.5220
例子4-8盡管只有短短的幾行,但是在003行使用了一個矩陣作為循環(huán)的索引值,于是,循環(huán)結(jié)果就分別計算矩陣的每一列元素的均值。和其他高級語言類似,MATLAB的循環(huán)結(jié)構(gòu)也可以進(jìn)行嵌套使用,使用嵌套的循環(huán)需要注意for關(guān)鍵字和end關(guān)鍵字之間的配對使用,請讀者根據(jù)高級語言的一般特性來推斷其運行的方式,這里就不再贅述了。4.3.3break語句和continue語句在循環(huán)結(jié)構(gòu)中還有兩條語句會影響程序的流程,這就是break語句和continue語句,這兩條語句的基本功能如下:●當(dāng)break語句使用在循環(huán)體中的時候,其作用是能夠在執(zhí)行循環(huán)體的時候強迫終止循環(huán),即控制程序的流程,使其提前退出循環(huán),它的使用方法是
break;●continue語句出現(xiàn)在循環(huán)體中的時候,其作用是能夠中斷本次的循環(huán)體運行,將程序的流程跳轉(zhuǎn)到判斷循環(huán)條件的語句處,繼續(xù)下一次的循環(huán),它的使用方法是
continue;[例子4-9]break語句示例——break_example.m。001 i=0;002 j=0;003 k=0;004 fori=1:2005 forj=1:2006 fork=1:2007 if(k==2)008 disp('退出循環(huán)');009 break;010 end011 str=sprintf('I=%d,J=%d,K=%d',i,j,k);012 disp(str);013 end014 end015 end016 disp('程序運行結(jié)束');例子4-9的運行結(jié)果如下:>>break_exampleI=1,J=1,K=1Exittheloop!I=1,J=2,K=1Exittheloop!I=2,J=1,K=1Exittheloop!I=2,J=2,K=1Exittheloop!Endtheprogram!break語句的作用是退出當(dāng)前的循環(huán)結(jié)構(gòu)運行,所以在例子4-8中,位于最內(nèi)層循環(huán)的break語句執(zhí)行的結(jié)果是退出了最內(nèi)層的循環(huán)k,位于外層的循環(huán)i和j還是都運行完畢了。[例子4-10]continue語句示例。001 i=0;002 fori=1:6003 if(i>3)004 continue005 else006 str=sprintf('I=%d',i);007 disp(str);008 end009 end010 str=sprintf('循環(huán)結(jié)束I=%d',i);011 disp(str);例子4-10的運行結(jié)果如下:>>continue_exampleI=1I=2I=3循環(huán)結(jié)束I=6continue語句的作用在例子4-9中得到了充分說明,該語句終止當(dāng)前的循環(huán),然后繼續(xù)下一次循環(huán)運算,直到所有的循環(huán)迭代運算結(jié)束為止。4.3.4提高運算性能
M語言和其他的高級語言不同,由于采用了解釋型語言,所以M語言的執(zhí)行效率肯定低于編譯型語言(例如C語言)。然而,隨著MATLAB版本的不斷升級,再加之合理利用MATLAB向量運算等特點可以較大幅度地提高M(jìn)語言代碼的執(zhí)行效率。在本小節(jié)結(jié)合一些具體的例子來講述M語言編程以及MATLAB軟件本身在提高程序執(zhí)行效率方面的一些特性。
1.向量化運算首先,希望讀者牢記這樣一點,MATLAB最初的目的是提供便利的矩陣數(shù)據(jù)操作能力。所以在大多數(shù)的應(yīng)用程序中,不要使用循環(huán)結(jié)構(gòu)操作矩陣的元素,應(yīng)直接使用矩陣元素的索引或者矩陣運算的函數(shù),這樣做不僅能夠提高代碼的執(zhí)行效率,而且還能夠提高程序的可讀性,這就是所謂的向量化的運算,也就是說,盡量將使用while循環(huán)或者for循環(huán)的語句結(jié)構(gòu)轉(zhuǎn)換成等價的向量或者矩陣運算,以提高程序的運算速度,參見例子4-11。[例子4-11]
向量化運算——array_vs_loops.m。001 Mass=rand(5,10000);002 Length=rand(5,10000);003 Width=rand(5,10000);004 Height=rand(5,10000);005 006 [rows,cols]=size(Mass);007 008 disp([char(10),'使用數(shù)組運算:'])009 tic010 Density=Mass./(Length.*Width.*Height);011 toc012013 disp([char(10),'使用循環(huán)結(jié)構(gòu):'])014 tic;015 forI=1:rows016 forJ=1:cols017 Density(I)=Mass(I,J)/(Length(I,J)*Width(I,J)*Height(I,J));018 end019 end020 toc
例子4-11比較了循環(huán)結(jié)構(gòu)和數(shù)組運算的執(zhí)行效率,分別使用數(shù)組運算010行和循環(huán)結(jié)構(gòu)015~019行完成了同樣的工作。程序的運行結(jié)果如下:>>array_vs_loops
UseArray:Elapsedtimeis0.002907seconds.
UseLoop:Elapsedtimeis0.007055seconds.
2.預(yù)分配存儲空間另外一種能夠提高運算效率的方法就是進(jìn)行內(nèi)存變量存儲空間的預(yù)分配,首先察看例子4-12。
[例子4-12]內(nèi)存預(yù)分配的例子——pre_allocate.m。001 disp([char(10),'使用內(nèi)存預(yù)分配:'])002 pre_allo=zeros(10000,1);003 tic;004 forI=1:10000005 pre_allo(I)=rand(1);006 end007 toc008 009 disp([char(10),'不使用內(nèi)存預(yù)分配:'])010 tic;011 forJ=1:10000012 not_pre_allo(J)=rand(1);013 end014 toc例子4-12的執(zhí)行結(jié)果如下:>>pre_allocate
Preallocation:Elapsedtimeis0.024410seconds.
Non-Preallocation:Elapsedtimeis0.223652seconds.
上面兩種不同的運算唯一的區(qū)別就是程序的002行,執(zhí)行這行語句之后,MATLAB自動分配了10000個連續(xù)的內(nèi)存空間用于存儲數(shù)據(jù),MATLAB將一次創(chuàng)建足夠的存儲空間,然后依次賦值。而后者not_pre_allo變量沒有進(jìn)行相應(yīng)的操作,所以帶來了兩次運算結(jié)果的不同。那么在不使用內(nèi)存預(yù)分配的運算中MATLAB進(jìn)行什么操作呢?當(dāng)I=1時,MATLAB將使用一小塊長度為一個單元大小的內(nèi)存保存一位隨機數(shù)。當(dāng)I=2時,MATLAB尋找一塊兩單元大小的內(nèi)存區(qū),一個單元放第一個隨機數(shù),第二個放另外一個隨機數(shù)。
……
當(dāng)I=10000時,MATLAB尋找一塊容納10000單元的內(nèi)存區(qū)存放以前的9999個隨機數(shù),同時把最新的一個隨機數(shù)加入進(jìn)去。代碼運行的結(jié)果造成了存儲空間的浪費,降低了程序的執(zhí)行速度。所以,在編寫M語言程序的時候需要盡量使用內(nèi)存的預(yù)分配,而少使用或者不使用數(shù)組內(nèi)存空間的自動擴充方式。MATLAB針對不同的數(shù)據(jù)類型有不同的內(nèi)存預(yù)分配函數(shù),見表4-2。表4-2內(nèi)存預(yù)分配函數(shù)
表4-2中說明了不同數(shù)據(jù)類型所要使用的預(yù)分配內(nèi)存函數(shù),其中結(jié)構(gòu)類型的數(shù)組需要兩個函數(shù)配合使用,利用struct函數(shù)構(gòu)造結(jié)構(gòu),而使用repmat函數(shù)創(chuàng)建數(shù)組。對于非雙精度類型的數(shù)據(jù),例如整數(shù)類型或者單精度類型進(jìn)行內(nèi)存的預(yù)分配時,需要使用相應(yīng)的構(gòu)造函數(shù)或者類型轉(zhuǎn)換函數(shù),例如:
Y=int16(zeros(1:10000));
在上面的表達(dá)式中創(chuàng)建了連續(xù)10000個16位整數(shù)的存儲空間。如果預(yù)先分配的內(nèi)存空間無法容納數(shù)據(jù),則可以通過repmat函數(shù)來擴充數(shù)組的存儲空間。上述函數(shù)的具體使用方法請讀者參閱MATLAB的幫助文檔或者在線幫助。此外,為了提高M(jìn)ATLAB編程性能,還需注意一些要點,見表4-3所示。
表4-3提高M(jìn)ATLAB編程性能的要點
4.4函數(shù)文件4.4.1基本結(jié)構(gòu)
M函數(shù)文件和腳本文件不同,函數(shù)文件不僅有自己特殊的文件格式,不同的函數(shù)還分別具有自己的工作空間。同其他高級語言類似,M函數(shù)文件也有局部變量和全局變量。讀者首先需要了解的是函數(shù)文件的基本結(jié)構(gòu),參見例子4-13。[例子4-13]
函數(shù)文件示例——average.m。001 functiony=average(x)002 %AVERAGE求向量元素的均值003 %語法:004 %Y=average(X)005 %其中,X是向量,Y為計算得到向量元素的均值006 %若輸入?yún)?shù)為非向量則出錯007 008 %代碼行009 [m,n]=size(x);010 %判斷輸入?yún)?shù)是否為向量011 if(~((m==1)|(n==1))|(m==1&n==1))012 %若輸入?yún)?shù)不是向量,則出錯013 error('Inputmustbeavector')014 end015 %計算向量元素的均值016 y=sum(x)/length(x);在MATLAB命令行中,鍵入下面的指令運行例子4-14的代碼:>>z=1:99;>>y=average(z)y=50M語言函數(shù)文件具有下面的不同部分:*函數(shù)定義行。*在線幫助。*注釋行。*M語言代碼。下面結(jié)合例子4-14分別說明這些部分的構(gòu)成。函數(shù)定義行,例子4-14的函數(shù)定義行為代碼的001行:
001 functiony=average(x)
這一行代碼中包括關(guān)鍵字function、函數(shù)輸出參數(shù)y、函數(shù)的名稱average和函數(shù)的輸入?yún)?shù)x。需要讀者注意的是函數(shù)的名稱,函數(shù)的名稱定義要求必須以字符開頭,后面可以用字符、數(shù)字和下劃線的組合構(gòu)成函數(shù)名稱。MATLAB對函數(shù)名稱的長度有限定,讀者可以在自己的MATLAB中,通過執(zhí)行namelengthmax函數(shù)獲取相應(yīng)的數(shù)值。假設(shè)該函數(shù)返回的數(shù)值為N,若函數(shù)的名稱長度超過了N,則MATLAB使用函數(shù)名稱的前N個字符作為函數(shù)名稱。一般地,推薦將函數(shù)名稱使用小寫的英文字符表示,同時保存函數(shù)的M文件名稱最好和函數(shù)名稱保持一致,若文件名稱和函數(shù)名稱不一致,則調(diào)用函數(shù)的時候需要使用文件名稱而非函數(shù)名稱。在新版本的MATLAB中,調(diào)用函數(shù)或者腳本的時候,調(diào)用指令的大小寫必須與函數(shù)或者腳本名稱的大小寫完全一致,否則會報告警告信息,例如,在MATLAB命令行窗體中鍵入下面的指令:
>>y=Average(z)Warning:Couldnotfindanexact(case-sensitive)matchfor'Average'.D:\Class\ML01\ch4\average.misacase-insensitivematchandwillbeusedinstead.Youcanimprovetheperformanceofyourcodebyusingexactnamematchesandwethereforerecommendthatyouupdateyourusageaccordingly.Alternatively,youcandisablethiswarningusingwarning('off','MATLAB:dispatcher:InexactMatch').
y= 50
在未來版本中,MATLAB會把這種調(diào)用指令大小寫與函數(shù)或者腳本不匹配的現(xiàn)象設(shè)定為錯誤。
M函數(shù)文件的在線幫助為緊隨在函數(shù)定義行的注釋行。在例子4-13中,average函數(shù)的在線幫助為002~006行的注釋行。若在MATLAB命令行窗體中鍵入下面的指令:>>helpaverageAVERAGE求向量元素的均值語法:
Y=average(X)
其中,X是向量,Y為計算得到向量元素的均值
若輸入?yún)?shù)為非向量則出錯
其中,在線幫助中比較重要而且特殊的是在線幫助的第一行,在MATLAB中將這行注釋稱為H1幫助行,它是在線幫助的第一行,若使用lookfor函數(shù)查詢函數(shù)時,僅查詢并顯示函數(shù)的H1幫助行,例如,在MATLAB命令行中鍵入下面的指令:
>>lookforaverage
在MATLAB的命令窗口中就會出現(xiàn):
AVERAGE求向量元素的均值
MEANAverageormeanvalue.…
由于H1幫助行的特殊作用,所以在用戶自己定義M函數(shù)文件時,一定要編寫相應(yīng)的H1幫助行,對函數(shù)進(jìn)行簡明、扼要的說明或者解釋。例子4-13的008、010、012、015行代碼分別是程序具體的注釋行,這些注釋行不會顯示在在線幫助中,主要原因就是這些注釋行沒有緊隨在H1幫助行的后面,其中008行的注釋與在線幫助之間有一個空行。其實從008行開始一直到文件的結(jié)尾都是M函數(shù)文件的代碼行,這些代碼行需要完成具體的算法,實現(xiàn)用戶的具體功能。代碼行就是用戶開發(fā)的算法M語言的實現(xiàn)。4.4.2輸入輸出參數(shù)
M語言函數(shù)文件的輸入、輸出參數(shù)和其他高級語言的輸入、輸出參數(shù)不同,在定義這些輸入、輸出參數(shù)的時候不需要指出變量的類型,因為MATLAB默認(rèn)這些參數(shù)都使用雙精度類型,這樣可以簡化程序的編寫。而且在定義參數(shù)時,也沒有確定輸入?yún)?shù)的維數(shù)或者尺寸,也就是說,直接從參數(shù)上無法判斷輸入來的是標(biāo)量、向量還是矩陣,只有通過程序內(nèi)部的具體代碼來加以判斷。
M語言的函數(shù)文件不僅可以有一個輸入?yún)?shù)和一個返回值,還可以為M語言函數(shù)文件定義多個輸入?yún)?shù)和多個輸出參數(shù),見例子4-14。[例子4-14]
多個輸入、輸出參數(shù)的M函數(shù)。001 function[avg,stdev,r]=ourstats(x,tol)002 %OURSTATS多輸入輸出參數(shù)示例003 %該函數(shù)計算處理矩陣,得到相應(yīng)的均值、004 %標(biāo)準(zhǔn)差和矩陣的秩005 [m,n]=size(x);006 ifm==1007 m=n;008 end009 %Average010 avg=sum(x)/m;011% Sandaddeviation012 stdev=sqrt(sum(x.^2)/m-avg.^2);013 %Rank014 s=svd(x);015 r=sum(s>tol);運行例子4-15,在MATLAB命令行中,鍵入下面的指令:>>A=[123;456]A=123456>>[a,s,r]=ourstats(A,0.1)a=2.50003.50004.5000s=1.50001.50001.5000r=2>>ourstats(A,0.1)ans=2.50003.50004.5000>>[a,s]=ourstats(A,0.1)a=2.50003.50004.5000s=1.50001.50001.5000>>[a,s,r,q]=ourstats(A,0.1)???Errorusing==>ourstatsToomanyoutputarguments.>>[a,s,r]=ourstats(A,0.1,1)???Errorusing==>ourstatsToomanyinputarguments.>>[a,s,r]=ourstats(A,0.1,q)???Undefinedfunctionorvariable'q'.
例子4-14的M代碼具有兩個輸入?yún)?shù)、三個輸出參數(shù),所以在使用該函數(shù)的時候,需要將必要的輸入、輸出參數(shù)寫明。注意調(diào)用該函數(shù)時的語法,將輸出參數(shù)依次寫在一個向量中,若輸出參數(shù)的個數(shù)與函數(shù)定義的輸出參數(shù)個數(shù)不一致,則在例子4-14中,將計算得到的前幾個輸出參數(shù)作為返回值,個數(shù)等于用戶指定的輸出參數(shù)個數(shù)。計算的結(jié)果依次賦值給不同的變量。4.4.3子函數(shù)同一個M函數(shù)文件中可以包含多個函數(shù)。如果在同一個M函數(shù)文件中包含了多個函數(shù),那么將出現(xiàn)在文件中的第一個M函數(shù)稱為主函數(shù)(primaryfunction),其余的函數(shù)稱為子函數(shù)(subfunction)。M函數(shù)文件的名稱一般與主函數(shù)的名稱保持一致,其他函數(shù)都必須按照函數(shù)的基本結(jié)構(gòu)來書寫,每一個函數(shù)的開始都是函數(shù)定義行,函數(shù)的結(jié)尾是另一個函數(shù)的定義行的開始或者整個M文件的結(jié)尾(最后一個子函數(shù)的結(jié)尾就是文件結(jié)束符)。不過,子函數(shù)不像主函數(shù),一般子函數(shù)沒有在線幫助,子函數(shù)的作用范圍有限,它只能被那些在定義子函數(shù)的M文件中定義的函數(shù)(包括主函數(shù)和其他子函數(shù))調(diào)用,不能被其他M文件定義的函數(shù)調(diào)用。
【例子4-15】子函數(shù)應(yīng)用示例001 function[avg,med]=newstats(u) %主函數(shù)002 %NEWSTATS計算均值和中間值003 n=length(u);004 avg=mean(u,n); %調(diào)用子函數(shù)005 med=median(u,n); %調(diào)用子函數(shù)006 007 functiona=mean(v,n) %子函數(shù)
008 %計算平均值009 a=sum(v)/n;010 011 functionm=median(v,n)%子函數(shù)
012 %計算中間值013 w=sort(v);014 ifrem(n,2)==1015 m=w((n+1)/2);016 else017 m=(w(n/2)+w(n/2+1))/2;018 end
運行例子4-15,在MATALB命令行窗口中鍵入下面的指令:>>x=1:11;>>[mean,mid]=newstats(x)mean=
6mid=6
在例子4-15的代碼中,分別在007行和011行定義了兩個子函數(shù)mean和median,這兩個子函數(shù)分別在主函數(shù)的004行和005行被調(diào)用。注意,在不同的函數(shù)之間傳遞變量是通過函數(shù)的參數(shù)形式來完成的。子函數(shù)的在線幫助也可以通過help指令來訪問,例如可以在MATLAB命令行窗體中鍵入下面的指令,從而查看子函數(shù)median的在線幫助:>>helpnewstats>median
計算中間值
4.4.4局部變量和全局變量同C語言類似,在M語言函數(shù)中也存在局部變量和全局變量。所謂局部變量,就是那些在M函數(shù)內(nèi)部聲明并使用的變量,這些變量僅能在函數(shù)調(diào)用執(zhí)行期間被使用,一旦函數(shù)結(jié)束運行,則這些變量占用的內(nèi)存空間將自動被釋放,變量的數(shù)值也就不存在了。這是由于MATLAB的解釋器在解釋執(zhí)行函數(shù)的時候,為不同的函數(shù)創(chuàng)建不同的工作空間,函數(shù)彼此的工作空間相互獨立,一旦函數(shù)執(zhí)行完畢,則函數(shù)的工作空間就不存在了。在本章前面的例子中,每個例子的函數(shù)內(nèi)部聲明使用的變量都是局部變量,所以函數(shù)執(zhí)行完畢后,MATLAB的基本工作空間中沒有這些變量存在,參見例子
4-16。
【例子4-16】局部變量的示例001 functionlocal002 %LOCAL查看局部變量的例子003 x=rand(2,2);004 y=zeros(2,2);005 z='函數(shù)中的變量';006 u={x,y,z};007 disp(z)
008 whos運行例子4-16,在MATLAB命令行窗體中鍵入下面的指令:>>local函數(shù)中的變量
NameSizeBytesClassAttributes
u1x3256cellx2x232doubley2x232doublez1x612char運行l(wèi)ocal函數(shù)之后,再次運行whos指令:>>whos沒有任何輸出。
通過運行l(wèi)ocal函數(shù)可以看到,所有在函數(shù)中創(chuàng)建的變量在函數(shù)運行結(jié)束后就不存在了,也就是說,局部變量的生存周期僅在函數(shù)活動期間。與局部變量相對應(yīng)的就是全局變量。MATLAB將全局變量保存在特殊的工作空間統(tǒng)一維護(hù)管理,將變量聲明為全局的方法就是在使用變量前,用關(guān)鍵字global聲明,例如聲明全局變量gXY:
>>globalgXY>>whosNameSizeBytesClassAttributes
gXY0x00
doubleglobal需要強調(diào)一點,MATLAB管理維護(hù)全局變量和局部變量使用了不同的工作空間,所以使用global關(guān)鍵字創(chuàng)建全局變量的時候有以下三種情況:
(1)若聲明為全局的變量在當(dāng)前的工作空間和全局工作空間都不存在,則創(chuàng)建一個新的變量,然后將這個變量賦值為空數(shù)組,該變量同時存在于局部工作空間和全局工作空間。
(2)若聲明為全局的變量已經(jīng)存在于全局工作空間,則不會在全局工作空間創(chuàng)建新的變量,其數(shù)值同時賦值給局部工作空間中的變量。
(3)若聲明為全局的變量存在于局部工作空間,而全局工作空間不存在,則系統(tǒng)會提示一個警告信息,同時將局部的變量“挪”到全局工作空間中。
【例子4-17】全局變量的示例在MATLAB命令行窗體中鍵入下面的指令:創(chuàng)建全局變量并賦值:>>globalmyx>>myx=10;變量的信息:>>whosNameSizeBytesClassAttributes
myx1x18double
global清除變量:>>clearmyx查看信息:>>whos當(dāng)前的工作空間下沒有任何變量,但是在全局工作空間下:>>whosglobalNameSizeBytesClassAttributes
myx1x18double
global在當(dāng)前工作空間再次創(chuàng)建變量:>>myx=23myx=23變量的信息:>>whosNameSizeBytesClassAttributes
myx1x18double將其修改為全局變量(注意警告信息):>>globalmyxWarning:Thevalueoflocalvariablesmayhavebeenchangedtomatchtheglobals.FutureversionsofMATLABwillrequirethatyoudeclareavariabletobeglobalbeforeyouusethatvariable.看看變量的數(shù)值:>>myxmyx=10清除當(dāng)前的工作空間:>>clear>>whosglobalNameSizeBytesClassAttributes
myx1x18double
global清除所有的內(nèi)存空間:>>clearall在全局工作空間下沒有任何變量了:>>whosglobal4.4.5函數(shù)執(zhí)行規(guī)則到這里,讀者應(yīng)該能夠創(chuàng)建自己的算法函數(shù),并且能夠執(zhí)行任何M語言函數(shù)了。只要在MATLAB的命令行窗口中鍵入函數(shù)的名稱,并且提供足夠的輸入/輸出參數(shù)就會得到正確的結(jié)果。如前文所述,M語言的函數(shù)被MATLAB的解釋器解釋執(zhí)行,所以,在本小節(jié)中將簡要討論一下解釋器解釋執(zhí)行程序的問題。
當(dāng)用戶在MATLAB命令行窗體鍵入一個命令或者執(zhí)行M語言文件中包含的一條語句或者指令時,MATLAB解釋器就負(fù)責(zé)解析用戶的輸入,并且給出相應(yīng)的答案。就目前而言,讀者能夠創(chuàng)建變量、創(chuàng)建自定義的函數(shù)和腳本文件,并且能夠編寫子函數(shù),在代碼中調(diào)用MATLAB的函數(shù)文件以及內(nèi)建函數(shù)等。那么,MATLAB解釋器解析命令的優(yōu)先級是怎樣的呢?n
首先判斷輸入的命令是否為變量。n
若不是內(nèi)存中的變量,判斷輸入的命令是否為MATLAB的內(nèi)建函數(shù)。n
若不是內(nèi)建函數(shù),則判斷輸入的命令是否為子函數(shù)。n
若在同一個路徑下發(fā)現(xiàn)同名的三種類型的文件:MEX文件、P代碼文件和M代碼文件,則優(yōu)先執(zhí)行MEX文件,其次是P代碼文件,最低的優(yōu)先級是M語言文件?!纠?-18】MATLAB命令解析優(yōu)先級在MATLAB命令行窗體中鍵入下面的指令:>>cos='Thisisastring!'cos=Thisisastring!>>cos(4)ans=s>>whichcoscosisavariable.>>clearall>>cos(4)ans=-0.6536>>whichcos
cosisabuilt-infunction.提示:
P代碼文件是從M文件用pcode命令生成的,
它是M文件經(jīng)過解析之后得到的代碼(P=Parse)。P代碼是經(jīng)過預(yù)編譯的無論何時函數(shù)被調(diào)用MATLAB都能訪問的現(xiàn)成代碼。因為
P文件是預(yù)編譯過的,所以它們的實際內(nèi)容對用戶而言是不可讀的,而且一般情況下它們比相應(yīng)的
M文件運行速度快。將M語言函數(shù)文件轉(zhuǎn)變?yōu)镻代碼文件的方法是:
>>pcodefun1fun2…4.5M文件調(diào)試4.5.1一般調(diào)試過程一般來說,應(yīng)用程序的錯誤有兩類,一類是語法錯誤,另一類是運行時錯誤。其中,語法錯誤包括了詞法或者文法的錯誤,例如函數(shù)名稱的錯誤拼寫等,而運行時錯誤是指那些程序運行過程得到的結(jié)果不是用戶需要的情況。不過不論是哪一種錯誤,都必須在開發(fā)的過程中將其找出,并且修正。由于M文件是一種解釋型語言,語法錯誤和運行時錯誤多數(shù)都是在運行過程中才能發(fā)現(xiàn),所以程序的調(diào)試往往是在程序無法得到正確結(jié)果時進(jìn)行程序修正的重要手段,特別是在早期版本的MATLAB中,程序調(diào)試是修正錯誤的唯一手段。不過,隨著MATLAB版本的不斷升級,發(fā)現(xiàn)定位M語言錯誤的手段也越來越豐富。例如,新版本的MATLAB提供的M語言編輯器能夠在代碼編寫過程中針對其中的語法錯誤進(jìn)行分析,并且會通過編輯器來提示相應(yīng)的錯誤信息,這一點在前面例子4-2中已經(jīng)討論過了,其實這也是一種輔助的代碼調(diào)試手段。
另外,從MATLABRelease14即MATLAB7.0開始,如果程序運行過程中出現(xiàn)錯誤,則在MATLAB命令行窗體提示信息中,以超鏈接的方式來顯示出現(xiàn)錯誤的代碼行位置,用戶只要單擊超鏈接,則可以打開M語言編輯器,并且自動定位到出現(xiàn)錯誤的代碼。此外,還可以使用M-LintCode、代碼的單元模式(CellMode)、路徑分析工具(DirectoryAnalysis)等來查找代碼中存在的錯誤。有關(guān)M-LintCode、代碼的單元模式(CellMode)、路徑分析工具(DirectoryAnalysis)等內(nèi)容已經(jīng)超出了本書的討論范圍,有興趣的讀者可以參閱《MATLAB高級編程》一書。
M語言編輯器既是M語言的文本編輯器,同時也是調(diào)試的可視化環(huán)境,在M語言編輯器下Debug菜單中的命令就能夠完成程序調(diào)試的所有功能,默認(rèn)情況下,大部分命令都是用來設(shè)置各種斷點,只有設(shè)置了斷點的應(yīng)用程序才能夠進(jìn)行調(diào)試。
在MATLAB中,程序斷點主要分為三類:n
標(biāo)準(zhǔn)斷點。n
條件斷點。n
錯誤斷點。這些斷點的設(shè)置都可以通過M語言編輯器下的Debug菜單中相應(yīng)的菜單命令來創(chuàng)建,如圖4-5所示。
圖4-5M文件編輯器的Debug菜單
[例子4-19]M文件調(diào)試代碼——stats_error.m。001 function[totalsum,average]=stats_error(input_vector)002 %STATS_ERROR-Calculatescumulativetotal&average003 totalsum=sum(input_vector);004 average=ourmean(input_vector);005 006 functiony=ourmean(x)007 %OURMEAN-Calculatesaverage008 [m,n]=size(x);009 ifm==1010 m=n;011 end012 y=sum(input_vector)/m;在MATLAB命令行窗體中嘗試執(zhí)行上面的函數(shù):>>[sumavg]=stats_error(rand(1,50))???Undefinedfunctionorvariable'input_vector'.
Errorin==>stats_error>ourmeanat12y=sum(input_vector)/m;Errorin==>stats_errorat4average=ourmean(input_vector);MATLAB首先提示程序運行有錯誤,并且指出錯誤發(fā)生的地點,單擊Errorin后面的超鏈接(具有下劃線文字的),可以直接在M語言編輯器中打開相應(yīng)的M代碼文件,并且光標(biāo)會停留在相應(yīng)的代碼行。這時,可以嘗試幾種不同的設(shè)置斷點的方法,因為這里的示例代碼在執(zhí)行過程中出現(xiàn)了錯誤,可以設(shè)置錯誤斷點,也可以直接在出現(xiàn)錯誤的代碼行處設(shè)置標(biāo)準(zhǔn)斷點。由于在前面的操作中,已經(jīng)自動定位到了出現(xiàn)錯誤的代碼行,故選擇設(shè)置標(biāo)準(zhǔn)斷點是比較好的選擇。設(shè)置標(biāo)準(zhǔn)斷點的方法如下:
在M語言編輯器打開代碼stats_error.m,將光標(biāo)置于代碼的第12行,然后執(zhí)行Debug菜單下的Set/ClearBreakpoint菜單命令,或者直接使用快捷鍵F12,或者用鼠標(biāo)直接單擊代碼行左側(cè)編輯器上的短橫線,還可以通過M語言編輯器工具欄上的按鈕來設(shè)置標(biāo)準(zhǔn)斷點。此時將在出現(xiàn)錯誤的代碼行(也就是代碼的第12行)設(shè)置斷點,設(shè)置斷點處用紅色的圓點標(biāo)識,如圖4-6所示。
圖4-6設(shè)置斷點
設(shè)置好斷點之后,再次在MATLAB命令行中運行函數(shù),這次運行MATLAB不會報告代碼運行錯誤,而是進(jìn)入到調(diào)試狀態(tài):>>[sumavg]=stats_error(rand(1,50))12y=sum(input_vector)/m;K>>進(jìn)入到調(diào)試狀態(tài)后,MATLAB的命令行窗體中會顯示當(dāng)前斷點的代碼行,并且命令行窗體提示符變成“K>>”,表示當(dāng)前MATLAB的狀態(tài)為調(diào)試狀態(tài)。此時,在M文件編輯器中第12行代碼前有綠色的箭頭,表示當(dāng)前程序運行在此處中斷,如圖4-7所示。
圖4-7M語言編輯器的調(diào)試模式
圖4-8調(diào)試程序的按鈕
另外,部分按鈕從編輯狀態(tài)進(jìn)入調(diào)試狀態(tài),如圖4-8所示。
通過M語言編輯器用戶界面中的Stack下拉列表框可以了解當(dāng)前應(yīng)用程序使用堆棧的狀態(tài),例如本例子中Stack下拉列表框包含ourmean,stats_error和Base,它們由下至上,分別為調(diào)用者和被調(diào)用者之間的關(guān)系,同時也顯示了當(dāng)前的工作空間。此時在MATLAB命令行窗體的“K>>”提示符下,可以任意鍵入MATLAB指令進(jìn)行運算和處理,不過需要注意,此時執(zhí)行指令的MATLAB工作空間就是當(dāng)前Stack下拉列表框中選擇的那個工作空間,例如,當(dāng)Stack下拉列表框為ourmean時,在MATLAB命令行窗體下鍵入指令:
K>>whosName SizeBytesClassm 1x18doublearrayn 1x18doublearrayx 1x50400doublearray再來看看調(diào)用函數(shù)時,MATLAB命令行窗體顯示的錯誤信息:???Undefinedfunctionorvariable'input_vector'.
可以看到,當(dāng)前的工作空間下沒有變量名input_vector,這也是該程序執(zhí)行出錯的原因,將程序中第12行的input_vector修改成為x就能得到正確的答案了。注意:如果需要修改代碼,一定要退出調(diào)試模式。如果不退出調(diào)試模式而修改了代碼,在保存代碼時,MATLAB將提示用戶,如圖4-9所示。
圖4-9退出調(diào)試模式的警告信息
4.5.2條件斷點所謂條件斷點,就是當(dāng)代碼執(zhí)行過程中,代碼的某個條件滿足時再進(jìn)入到調(diào)試模式。這種條件斷點對于調(diào)試那些循環(huán)結(jié)構(gòu)代碼時非常有效,因為循環(huán)體內(nèi)的代碼很有可能是在循環(huán)的某個階段才出現(xiàn)錯誤,也就是說,當(dāng)循環(huán)變量達(dá)到某個數(shù)值時才出現(xiàn)錯誤。早期版本的MATLAB沒有條件斷點的功能,只能使用標(biāo)準(zhǔn)斷點來進(jìn)行調(diào)試,對于老版本的MATLAB用戶來說,這是非常痛苦的一件事情。
下面使用例4-7的代碼演示設(shè)置條件斷點的方法。001 sum=0;002 fori=1:1000003 sum=sum+i;004 end 005 str=['Theresult:',num2str(sum)];006 disp(str)條件斷點其實可以設(shè)置在代碼的任意行,只要能夠滿足相應(yīng)的條件就會中斷當(dāng)前程序執(zhí)行進(jìn)入到調(diào)試模式,這里將斷點設(shè)置在循環(huán)體內(nèi),也即是代碼的003行。首先,把光標(biāo)放置在需要設(shè)置斷點的代碼行,然后執(zhí)行M語言編輯器中Debug菜單下的Set/ModifyConditionBreakpoint菜單命令,此時將彈出斷點設(shè)置對話框,如圖4-10所示。
圖4-10設(shè)置條件斷點
4.5.3錯誤斷點所謂錯誤斷點,就是在程序執(zhí)行過程中,如果出現(xiàn)了錯誤或者警告信息,則自動中斷當(dāng)前程序執(zhí)行,并且進(jìn)入到調(diào)試模式下。由于這種斷點是在程序執(zhí)行出現(xiàn)錯誤的時候自動實現(xiàn)程序中斷,并且進(jìn)入調(diào)試模式,所以又叫做自動斷點。其實在早期版本的MATLAB中就已經(jīng)存在自動斷點了,而從MATLABRelease14開始,在這方面進(jìn)行了增強。設(shè)置錯誤斷點,需要執(zhí)行M語言編輯器中Debug菜單下的StopifErrors/Warnings命令,此時將
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度生態(tài)園區(qū)沉降監(jiān)測與可持續(xù)發(fā)展合同范本4篇
- 2025年度瓷磚品牌形象設(shè)計與廣告投放合同3篇
- 2024石料運輸合同違約責(zé)任范本3篇
- 2025年度政府機構(gòu)公務(wù)出差協(xié)議書模板4篇
- 2025年度智慧家居SAAS解決方案銷售服務(wù)合同3篇
- 2024版?zhèn)€人之間借款合同書
- 2025年度幼兒園廚房設(shè)備租賃及運營管理合同4篇
- 2024門窗行業(yè)綠色認(rèn)證與環(huán)保評估合同3篇
- 2025年度智能設(shè)備品牌代理授權(quán)合同協(xié)議4篇
- 2025年度智能交通系統(tǒng)出資股東協(xié)議范本4篇
- 2025年中國高純生鐵行業(yè)政策、市場規(guī)模及投資前景研究報告(智研咨詢發(fā)布)
- 湖北省黃石市陽新縣2024-2025學(xué)年八年級上學(xué)期數(shù)學(xué)期末考試題 含答案
- 2022-2024年浙江中考英語試題匯編:完形填空(學(xué)生版)
- 2025年廣東省廣州市荔灣區(qū)各街道辦事處招聘90人歷年高頻重點提升(共500題)附帶答案詳解
- 中試部培訓(xùn)資料
- 硝化棉是天然纖維素硝化棉制造行業(yè)分析報告
- 央視網(wǎng)2025亞冬會營銷方案
- 北師大版數(shù)學(xué)三年級下冊豎式計算題100道
- 計算機網(wǎng)絡(luò)技術(shù)全套教學(xué)課件
- 《無砟軌道施工與組織》 課件 第十講雙塊式無砟軌道施工工藝
- 屋頂分布式光伏發(fā)電項目施工重點難點分析及應(yīng)對措施
評論
0/150
提交評論