聲明:本系列文章參考了《MATLAB 8.X實戰(zhàn)指南(R2014a中文版)》(清華大學出版社,趙小川等編著),僅用于個人學習總結(jié)和交流,禁止作為商業(yè)用途轉(zhuǎn)載或使用。
每種編程語言都有各自特定的語法,其實很多編程語言的基礎(chǔ)語法都是非常類似的,比如大多數(shù)(高級)編程語言都會包含如下幾種語法元素:
- 變量
- 運算符
- 控制語句:判斷語句、循環(huán)語句等
- 函數(shù)
Matlab也不例外,本文將會對Matlab的基礎(chǔ)語法進行一個梳理。
注:本文中使用的Matlab是超精簡版、免安裝的Matlab 5.3綠色版本(下載地址)
變量
變量命名規(guī)則
可以由英文字母、數(shù)字或下劃線組成,但必須以字母開頭。注意:變量名不要使用Matlab中的保留關(guān)鍵字。用iskeyword函數(shù)可以查看Matlab中所有的關(guān)鍵字。
變量作用域
有如下三種作用域的變量:
局部變量
每個函數(shù)(函數(shù)會在后面細講)中定義的變量,只能在當前函數(shù)體內(nèi)訪問到。全局變量
在函數(shù)體中用global關(guān)鍵字聲明的變量,它的作用域是:所有的函數(shù)和Matlab工作空間。任何一個地方改變了全局變量的值,其他所有使用到它的地方的值都會隨著改變。建議盡量少使用全局變量。靜態(tài)變量
在一個函數(shù)中可以使用persistent關(guān)鍵字聲明一個靜態(tài)變量,只要函數(shù)存在,靜態(tài)變量就不會被清除。
運算符
Matlab的運算符包括:加減乘除四則運算、冪指對、邏輯運算符等。
判斷語句
if語句
- if-end語句
舉個栗子:
?if 1 + 1 == 2
disp('1+1 is 2!');
end
1+1 is 2!
?
if-else-end語句
用法與if-end語句類似,不再舉例。if-elseif-end語句
if-elseif-else-end語句
注:這里的elseif可以有多個。
switch語句
舉個栗子:
?x = 'C';
?switch x
case {'A','a'}
r = '優(yōu)秀'
case {'B','b'}
r = '良好'
case {'C','c'}
r = '一般'
case {'D','d'}
r = '及格'
otherwise
r = '不及格'
end
r =
一般
注:switch語句可以沒有otherwise分支。
循環(huán)語句
for語句
for語句的格式:
for index = start:increment:end
語句塊
end
% 其中index為循環(huán)變量,start為循環(huán)起始值,end為循環(huán)終止值,increment為每次的增量,可以不寫,默認為1。如果increment為負數(shù),則循環(huán)會在start小于end的時候終止。
舉個栗子,求1~100的累加和:
?sum = 0;
?for i = 1 : 100
sum = sum + i;
end
?disp(sum)
5050
while語句
在循環(huán)次數(shù)未知的時候,就不能用for語句了,這個時候可以使用while語句,語法格式:
while 邏輯表達式
語句塊
end
舉個栗子,用while語句來計算1~100的累加和:
?i = 1;
?sum = 0;
?while i <= 100
sum = sum + i;
i = i + 1;
end
?disp(sum)
5050
continue語句
如果想跳過某次循環(huán),可以使用continue語句,比如下面的栗子是計算1~10之間偶數(shù)的和:
?sum = 0;
?for i = 1:10
if mod(i,2) ~= 0
continue
end
sum = sum + i;
end
?disp(sum)
30
break語句
用于終止循環(huán)。舉個栗子,遍歷1~10,遇到7就終止循環(huán):
?for i = 1:10
if i == 7
break;
end
end
?disp(i)
7
異常處理語句
當程序發(fā)生異常時,需要捕獲異常并對異常進行處理,這個時候需要用到try-catch語句,基本語法格式:
try
語句塊1
catch
語句塊2
end
% 如果語句塊1發(fā)生異常,會跳到語句塊2
Matlab腳本文件(m文件)
和其他編程語言一樣,比如Java的代碼文件為java文件,C++的代碼文件為cpp文件,Python的代碼文件為py文件,Matlab也有自己的代碼文件,是以.m作為后綴名的文件。
一個m文件可以看作是一堆代碼語句的集合,在m文件中可以加注釋,每一行代碼中%后面的內(nèi)容都是注釋。
函數(shù)
Matlab的函數(shù)分為兩種,一種叫m函數(shù),也叫主函數(shù),是定義在和函數(shù)同名的m文件中的函數(shù),可以供外部(Matlab命令行窗口或者其他m文件)調(diào)用;另一種叫子函數(shù),也是寫在m文件中,但是只能供同一m文件中的主函數(shù)或其他子函數(shù)調(diào)用。
m函數(shù)
m函數(shù)需要定義在與函數(shù)同名的m文件中,一個m函數(shù)具有獨立的工作空間。一般由5部分組成:函數(shù)定義行、H1行(緊跟函數(shù)定義行后面一行的注釋文本,也是用lookfor 函數(shù)名命令時候可以看到的文本)、幫助文本(注釋文本,用于對函數(shù)的功能、輸入?yún)?shù)、輸出參數(shù)等信息進行說明)、函數(shù)體、注釋。
Matlab帶有m文件編輯器,可以在Matlab命令行中輸入edit命令打開m文件編輯器,然后在其中就可以編輯m文件。當然,在記事本或notepad++中也是可以編輯m文件的,就好比既可以在Eclipse中寫Java代碼,如果你喜歡也可以在記事本或vim編輯器中寫。
下面舉一個栗子來說明m函數(shù)的定義方法:
function result = myadd(num1,num2)
% myadd(num1,num2) 自定義加法函數(shù),計算num1和num2的和
% 輸入?yún)?shù)為兩個數(shù)
% 輸出參數(shù)為兩個數(shù)的和
% 程序作者:m2fox
% 程序開發(fā)日期:2017-11-21
result = num1 + num2
把上面一段代碼保存成一個m文件,命名為:myadd.m,保存,比如保存在了D:\mylearn\目錄下。
然后要把D:\mylearn\這個路徑添加為Matlab的執(zhí)行路徑(相當于環(huán)境變量),否則無法在命令行窗口中調(diào)用myadd函數(shù)。添加執(zhí)行路徑的方法是:



把D:\mylearn\這個路徑按照上述方法添加到執(zhí)行路徑后,就可以到Matlab命令行中輸入myadd(num1,num2)命令來求兩個數(shù)的和了,示例程序如下:
?myadd(1,2);
result =
3
?help myadd
myadd(num1,num2) 自定義加法函數(shù),計算num1和num2的和
輸入?yún)?shù)為兩個數(shù)
輸出參數(shù)為兩個數(shù)的和
程序作者:m2fox
程序開發(fā)日期:2017-11-21
?lookfor myadd
myadd.m: % myadd(num1,num2) 自定義加法函數(shù),計算num1和num2的和
可以看到,求出了1+2的結(jié)果:3,然后用help和lookfor命令也顯示出了定義函數(shù)時寫的函數(shù)幫助文本。
子函數(shù)
在文件中,和文件名同名的函數(shù)稱為m函數(shù),也叫主函數(shù);而在m文件中定義的其他函數(shù),則稱為子函數(shù)。要注意的是,子函數(shù)之內(nèi)被當前m文件內(nèi)部的主函數(shù)以及其他子函數(shù)調(diào)用,不能被外部調(diào)用。下面舉一個子函數(shù)的栗子,還是在剛剛的myadd.m文件中定義:
function result = myadd(num1,num2)
% myadd(num1,num2) 自定義加法函數(shù),計算num1和num2的平方和
% 輸入?yún)?shù)為兩個數(shù)
% 輸出參數(shù)為兩個數(shù)的平方和
% 程序作者:m2fox
% 程序開發(fā)日期:2017-11-21
result = square(num1) + square(num2)
function s = square(x)
% 這是一個子函數(shù),用于算一個數(shù)的平方
s = x ^ 2;
保存文件,再在Matlab命令行中輸入調(diào)用myadd函數(shù):
?myadd(1,2);
result =
5
函數(shù)句柄和匿名函數(shù)
如果你接觸過Python,會知道在Python中函數(shù)也是一種對象,可以將一個函數(shù)賦值給一個變量。在Python中也有l(wèi)ambda表達式支持的匿名函數(shù)。
類似的,Matlab中也有類似函數(shù)對象的函數(shù)句柄以及匿名函數(shù)。
函數(shù)句柄:
變量名 = @函數(shù)名,經(jīng)過這一句的定義之后,就可以用自己定義的變量名來調(diào)用這個函數(shù)了。匿名函數(shù):
變量名 = @(輸入?yún)?shù)列表)(運算表達式)
注:函數(shù)句柄和匿名函數(shù)在精簡版Matlab 5.3中不支持,所以此處不再給出示例程序。
獲取一個函數(shù)的輸入?yún)?shù)數(shù)量
舉例如下,修改myadd.m文件的內(nèi)容并保存:
function result = myadd(num1,num2)
% 如果輸入的參數(shù)只有一個,就輸出這個數(shù)的絕對值;如果輸入的參數(shù)有兩個,就輸出這兩個數(shù)的和
if (nargin == 1) % 用nargin這個特殊變量來獲取輸入?yún)?shù)的個數(shù)
result = abs(num1)
elseif (nargin == 2)
result = num1 + num2
end
在Matlab命令行中調(diào)用myadd函數(shù):
?myadd(-3);
result =
3
?myadd(4,5);
result =
9
幾點實用編程技巧
計算函數(shù)用時
在任意代碼段的開始和結(jié)束使用tic和toc語句對,可以計算這段代碼的用時,編寫一個名為myadd.m的m函數(shù)如下:
function sum = myadd()
tic
s = 0;
for i = 1:1000000
s = s + 1/i;
end
sum = s;
toc
在命令行中調(diào)用myadd函數(shù):
?myadd
elapsed_time =
1.1740
ans =
14.3927
可以看到myadd函數(shù)用時1.174秒,結(jié)果為14.3927
用向量化的操作來代替循環(huán)操作
向量化的操作相比循環(huán)操作而言,在數(shù)據(jù)量大的時候性能將會顯著提高。
比如對比如下兩個函數(shù):
function result = myadd1()
tic
s = 0;
for i = 1:1000000
s = s + 1/i;
end
result = s;
toc
function result = myadd2()
tic
i = 1:1000000;
result = sum(1./i);
toc
分別調(diào)用myadd1、myadd2函數(shù),結(jié)果對比如下:
?myadd1
elapsed_time =
1.1740
ans =
14.3927
?myadd2
elapsed_time =
0.0200
ans =
14.3927
可以看出,采用向量化的操作后,相比使用循環(huán),同樣的數(shù)據(jù)量的計算效率得到了幾十倍的提升。
次數(shù)多的循環(huán)放在內(nèi)層,次數(shù)少的循環(huán)放在外層
可以防止損耗過多程序性能。
大型矩陣預先定維
先使用zeros或ones函數(shù)對大型矩陣預先定維,將會顯著降低程序耗時。