Matlab编程基础
“Matlab”是“Matrix?Laboratory” 的縮寫,中文“矩陣實驗室”,是強大的數學工具。本文側重于Matlab的編程語言側面,講述Matlab的基本語法,以及用Matlab語言進行程序設計。值得一提的是,Matlab從R2014a版本開始支持中文語言了!
1.基本概念
Matlab默認啟動后界面:
Matlab有關的文件后綴:
| File Extension | Description |
| .m | MATLAB Code — A MATLAB script, function, or class. |
| .p | MATLAB P-Code — Protected function file. |
| .mat | MATLAB Data — Binary file that stores MATLAB variables. |
| .fig | MATLAB Figure. |
| .mdl,?.slx | Simulink Model. |
| .mdlp,?.slxp | Simulink Protected Model. |
| .mex | MATLAB MEX — Shared library files that can be dynamically loaded into MATLAB. The MEX-file extensions are platform-dependent. |
參考Matlab R2014a幫助文檔“MathWorks File Extensions”,搜索即可,下同。
命令行執行命令:
可以在命令行窗口(Matlab默認啟后動界面的中間)中執行命令,除了運算公式外,關閉Matlab、改變當前文件夾、新建.m文件之類的都可以以命令形式執行,下面對最為常用的基本命令進行總結:
| Class | Function | Description |
| Shutdown | exit,?quit | Terminate MATLAB program |
| Search Path | pwd | Identify current folder |
| cd | Change current folder | |
| dir,?ls | List folder contents | |
| type | Display contents of file | |
| what | List MATLAB files in folder | |
| path | View or change search path | |
| which | Locate functions and files | |
| Command History | clc | Clear Command Window |
| diary | Save Command Window text to file | |
| Help | format | Set display format for output |
| help | Help for functions in Command Window | |
| doc | Reference page in Help browser | |
| iskeyword | Determine whether input is MATLAB keyword | |
| WorkSpace | clear | Remove items from workspace, freeing up system memory |
| clf | Clear current figure window | |
| pack | Consolidate workspace memory | |
| who | List variables in workspace | |
| whos | List variables in workspace, with sizes and types | |
| save | Save workspace variables to file | |
| load | Load data from MAT-file into workspace | |
| Other | disp | Display text or array |
| display | Display text or array (overloaded method) | |
| tic,?toc | Start stopwatch timer(Read elapsed time from stopwatch) |
上面所有函數都可以用“help funcName”或“doc funcName”命令查看幫助,參考Matlab R2012a幫助文檔“MATLAB/Functions”。
當前文件夾(Current Folder)和搜索路徑(Search Path):
Matlab之所以強大,很重要的原因是它實現了很多數學算法,也就是有一個龐大的函數庫。和其他編程語言一樣,這些函數以實現文件或源文件形式存在(.m,.p,.mex等)。在我們執行命令(或者說是運行m code)時,例如“y=sin(x)”,Matlab需要搜索“sin”,這就是在“當前文件夾”和“搜索路徑”中進行的。Matlab以“文件名”進行搜索,所以要求函數(Main Function)等名子和文件名相同。
“當前文件夾”就是程序員的工作文件夾,里面有我們寫的M代碼,在上圖Matlab默認啟動后界面中“當前文件夾”如紅色框所示,其內容可以在左側瀏覽。初用Matlab的人可能遇到過這個問題:打開一個.m文件,點擊“運行”按鈕,出現如下提示(如果你的Matlab版本不是最新的,那就是英語提示):
這是因為當我們點“運行”(或快捷鍵F5)時,其實相當于在命令行執行命令運行文件,Matlab搜索當前文件夾和搜索路徑,但沒找到。
要設置添加搜索路徑,可以在菜單“主頁 >> 環境 >> 設置路徑”中進行(也可以用命令形式):
工作區(WorkSpace):
“工作區”類似于棧,是運行Matlab命令(或程序)時在內存產生變量的集合(也就是說它是一塊內存區域),在Matlab默認啟動后界面中顯示在右側。在“工作區”窗口顯示的所有變量,可以雙擊查看其內容,也可以修改或刪除。工作區分基本工作區(Base Workspace)和函數工作區(Function Workspace),函數工作區一般在函數調用過程中產生,我們一般接觸的就是基本工作區。基本工作區中的變量在關閉Matlab前都不會自動清除,除非用clear命令,所以如果想讓程序不依賴于歷史數據的話,最好在運行程序前執行“clear all”命令。參考Matlab R2014a幫助文檔“Base and Function Workspaces”。
M腳本文件:
所有可以在命令行窗口中輸入的命令都可以出現在.m文件中,這里的所謂腳本文件就是我們通常說的Matlab程序。關于Matlab程序有幾個最為基本的點需要知道:以“%”開頭的行是注釋;語句后面加“;”可以讓Matlab執行語句但不輸出結果;一行代碼太長寫不下用“...”續行;Matlab程序一般是解釋執行,所以有些錯誤在執行時才會報告。
2.基本語法
首先來看Matlab的符號表(參考Matlab R2014a幫助文檔“Symbol Reference”):
| Name | Symbol | Description |
| Asterisk | * | Filename Wildcard |
| At | @ | Function Handle Constructor Class Folder Designator |
| Colon | : | Numeric Sequence Range(step) Indexing Range Specifier Conversion to Column Vector Preserving Array Shape on Assignment |
| Comma | , | Row Element Separator Array Index Separator Function Input and Output Separator Command or Statement Separator |
| Curly Braces | { } | Cell Array Constructor Cell Array Indexing |
| Dot | . | Decimal Point Structure Field Definition Object Method Specifier |
| Dot-Dot | .. | Parent Folder |
| Dot-Dot-Dot (Ellipsis) | … | Line Continuation Entering Long Strings Defining Arrays |
| Dot-Parentheses | .( ) | Dynamic Structure Fields |
| Exclamation Point | ! | Shell Escape |
| Parentheses | ( ) | Array Indexing Function Input Arguments |
| Percent | % | Single Line Comments Conversion Specifiers |
| Percent-Brace | %{ %} | Block Comments |
| Plus | + | Designate the names of package folders |
| Semicolon | ; | Array Row Separator Output Suppression Command or Statement Separator |
| Single Quotes | ‘ ’ | Character and String Constructor |
| Space Character | Space | Row Element Separator Function Output Separator |
| Slash and Backslash | / \ | Separate the elements of a path or folder string |
| Square Brackets | [ ] | Array Constructor Concatenation Function Declarations and Calls |
| Tilde | ~ | Not Equal to Logical NOT Argument Placeholder |
下圖清晰的說明了Matlab的基本數據類型(類)(取自Matlab R2014a幫助文檔“Fundamental MATLAB Classes”),其中double是默認數據類型,字符串用單引號‘’:
Matlab是高級動態語言,變量(對象)在使用之前不需要聲明,標識符的第一次出現視為變量的創建,標識符由字母開頭接字母數字或下劃線的不超過63個字符組成。一個標識符只是一個引用,它可以指向任意類型,比如執行“a=1”后,a作為一個名字指向double型變量,再執行“a=’hello’”后,a又指向一個字符串變量,原來的double變量因為不再引用而進入垃圾回收,這和Python類似。
對于邏輯類型(布爾類型),和C語言類似,Matlab將非 0 數看做 true,0 看做 false,Matlab將邏輯型輸出為 0 和 1。
Matlab號稱是矩陣實驗室,除了函數句柄和多維數組外,每個變量都看做是矩陣(二維數組),標量被看做1x1矩陣,一維數組被看做1xN或Nx1矩陣,Matlab支持將矩陣作為整體進行運算。矩陣的行元素間用空格或逗號“,”分隔,列元素間用回車或分號“;”分隔,矩陣用中括號“[]”表示,索引數組用小括號“()”(從1開始,多維數組各維索引用逗號隔開),如下例所示:
Matlab內置了一些常量或約定名字(參考Matlab R2014a幫助文檔“Special Values”、Matlab R2012a幫助文檔“MATLAB/Functions/Mathematics/Math Constants”):
| Name | Description |
| eps | Floating-point relative accuracy |
| i,?j | Imaginary unit |
| Inf | Infinity |
| NaN | Not-a-Number |
| pi | Ratio of circle's circumference to its diameter |
| intmax?(intmin) | Largest(Smallest) value of specified integer type |
| realmax?(realmin) | Largest positive(Smallest positive normalized) floating-point number |
| ans | Most recent answer (variable) |
Matlab基本算符和表達式(參考Matlab R2014a幫助文檔“Operators and Elementary Operations”、Matlab R2012a幫助文檔“MATLAB/User’s Guide/Programming Fundamentals/Language/Program Components/Operators”、《MATLAB R2011a教程》第3章p130、p138、p139):
| Class | Description | Array operator | Matrix operator |
| Arithmetic | Addition | + | + |
| Subtraction | - | - | |
| Multiplication | .* | * | |
| Right(Left) division | ./(.\) | /(\) | |
| Power | .^ | ^ | |
| Transpose | .’ | ’?(Complex conjugate transpose) | |
| Relational | Less than | <? | ? |
| Less than or equal to | <= | ? | |
| Greater than | >? | ? | |
| Greater than or equal to | >= | ? | |
| Equal to | == | ? | |
| Not equal to | ~= | ? | |
| Logical | And | & | ? |
| Or | | | ? | |
| Not | ~ | ? | |
| Xor | xor | ? | |
| Bit-Wise | Bit-and | bitand | ? |
| Bit-or | bitor | ? | |
| Bit-xor | bitxor | ? | |
| Short-Circuit | And | && | ? |
| Or | || | ? |
其中,“數組運算”指的是兩個尺寸相同(行數列數相同)數組(或一個是標量)逐個元素之間進行運算得到尺寸相同的數組作為結果,“矩陣運算”則是按照數學上矩陣的運算法則運算。下面是一些例子:
其中,a、b、c 都是double類型,l 是Logical類型(布爾類型數組)。
Matlab和其他大多數語言相同,有如下控制流(參考Matlab R2014a幫助文檔“Control Flow”),Matlab代碼是Pascal風格的,需要以end結尾:
| Class | Control-Flow | Syntax | Remarks |
| Conditional Statements | if-else | if?expression ?? statements elseif?expression ?? statements else ?? statements end | |
| switch-case | switch?switch_expression ???case?case_expression ????? statements ???case?case_expression ????? statements ??? ... ???otherwise ???? ?statements end | only one case(or otherwise) statement will be executed | |
| Loop Control Statements | for | for?index = values ?? program statements ????????? : end | break, continue |
| parallel-for | parfor?loopvar = initval:endval; statements;?end parfor?(loopvar = initval:endval, M); statements;?end | ||
| while | while?expression ?? statements end | break, continue | |
| Other | pause | pause pause(n) pause?on pause?off pause?query state =?pause('query') oldstate =?pause(newstate) | |
| return | return | return to the invoking function or to the keyboard | |
| try-catch | try ?? statements catch?exception ?? statements end | ||
| assert | assert(expression) assert(expression, 'msgString') assert(expression, 'msgString', value1, value2, ...) assert(expression, 'msgIdent', 'msgString', value1, value2, ...) | ||
| warning | warning('message') warning('message', a1, a2,...) warning('message_id', 'message') warning('message_id', 'message', a1, a2, ..., an) s =?warning(state, 'message_id') s =?warning(state, mode) | ||
| error | error('msgIdent', 'msgString', v1, v2, ..., vN) error('msgString', v1, v2, ...) error('msgString') error(msgStruct) | ||
| input | result =?input(prompt)?(displays the prompt string on the screen, waits for input from the keyboard, evaluates any expressions in the input, and returns the result.) str =?input(prompt,'s')?(returns the entered text as a MATLAB string, without evaluating expressions.) | ||
| keyboard | keyboard?(when placed in a program .m file, stops execution of the file and gives control to the keyboard.) |
3.函數
Matlab的函數以M函數文件(后綴.m)形式存在,主函數(Main Function,這里主函數和C語言主函數不同,它指該函數文件中第一個定義的函數,可以理解為文件的對外接口)名要和文件名相同,一個主函數的例子如下(文件“rank.m”,位于“C:\Program Files\MATLAB\R2014a\toolbox\matlab\matfun\”):
1 function r = rank(A,tol)2 % RANK Matrix rank.3 % RANK(A) provides an estimate of the number of linearly4 % independent rows or columns of a matrix A.5 % RANK(A,tol) is the number of singular values of A6 % that are larger than tol.7 % RANK(A) uses the default tol = max(size(A)) * norm(A) * eps.8 9 s = svd(A); 10 if nargin==1 11 tol = max(size(A)') * max(s) * eps; 12 end 13 r = sum(s > tol);上面文件首行以function開頭的稱為函數聲明行(function declaration line),緊接一行注釋稱為H1行(用作lookfor指令),H1行及之后的連續注釋稱為在線幫助文本(help text,用作help指令),再之后的注釋稱為編寫和修改記錄(上面例子中沒有,用作軟件歸檔管理),之后是函數體。當然,除函數聲明和函數體外其他都是可選的。
除主函數(main function)外,還有局部函數(Local functions),它定義在M函數文件里的除第一個位置外的地方(所以,它只能依附在主函數文件中,不能出現在M腳本文件中),它只在該文件內可見,下面是一個例子(取自Matlab R2014幫助文檔“Local Functions”,文件“mystats.m”):
1 function [avg, med] = mystats(x)2 n = length(x);3 avg = mymean(x,n);4 med = mymedian(x,n);5 end6 7 function a = mymean(v,n)8 % MYMEAN Example of a local function.9 10 a = sum(v)/n; 11 end 12 13 function m = mymedian(v,n) 14 % MYMEDIAN Another example of a local function. 15 16 w = sort(v); 17 if rem(n,2) == 1 18 m = w((n + 1)/2); 19 else 20 m = (w(n/2) + w(n/2 + 1))/2; 21 end 22 end另外,還有嵌套函數(Nested Functions),顧名思義,它定義在別的函數內,如下例子(取自Matlab R2014幫助文檔“Nested Functions”,文件“parent.m”):
1 function parent 2 disp('This is the parent function') 3 nestedfx 4 5 function nestedfx 6 disp('This is the nested function') 7 end 8 9 end嵌套函數和其他函數的區別是,它可以使用包含它的父函數的變量,也就是說,它可以使用除了參數及在函數內部定義的變量之外的變量,這涉及函數工作區(Function Workspace)的概念,前面說過有個基本工作區,函數調用時產生函數工作區,見例子。
當前文件夾里有兩個文件:abc.m,f.m,f.m是M函數文件,abc.m是M腳本文件,其內容如下:
1 % f.m 2 function [ out ] = f( x ) 3 out = x^2+6; 4 end 1 % abc.m 2 a = 9; 3 b = 10; 4 c = [1 2 3]; 5 d = f(a); 6 d運行abc.m后工作區如下(基本工作區):
在f.m中設置如下斷點(第三行紅點):
再運行abc.m,程序停在斷點處,此時工作區和調試界面如下:
我們可以類比C語言的函數調用棧來理解函數工作區。想要跨越函數工作區傳遞變量可以用 global 關鍵字聲明全局共享變量,要在函數內部定義類似C語言的?static 變量,使用 persistent 關鍵字聲明變量。
函數句柄(function_handle)類似于C語言的函數指針,它用“@”來創建,如下是一個例子(接上面):
這樣我們在調用函數時就可以這樣寫:
b=fh(a)有了函數句柄,我們就可以創建匿名函數(Anonymous Functions):
sqr = @(x) x.^2; a = sqr(5);利用nargin和nargout可以實現以不同于函數定義的參數和返回值個數調用函數,例子如下(取自Matlab R2014幫助文檔):
1 % file: addme.m2 function c = addme(a,b)3 switch nargin4 case 25 c = a + b;6 case 17 c = a + a;8 otherwise9 c = 0; 10 end 1 % file: subtract.m 2 function [dif,absdif] = subtract(y,x) 3 dif = y - x; 4 if nargout > 1 5 disp('Calculating absolute value') 6 absdif = abs(dif); 7 end利用varargin和varargout可以實現可變參數和返回值列表,例子如下(取自Matlab R2014幫助文檔):
1 % file: varlist.m 2 function varlist(varargin) 3 fprintf('Number of arguments: %d\n',nargin); 4 celldisp(varargin) 1 % file: sizeout.m 2 function [s,varargout] = sizeout(x) 3 nout = max(nargout,1) - 1; 4 s = size(x); 5 for k=1:nout 6 varargout{k} = s(k); 7 endMatlab函數的參數只是個符號,它本身可以是任何類型,可以是標量或向量或矩陣,可以在函數內部利用一些內置指令來得到參數個數類型等信息,這就是說,Matlab的函數本身是多態或是重載的。為方便進行程序設計,Matlab任然支持顯示的函數重載,參考Matlab R2014a幫助文檔“Types of Functions”、Matlab R2012a幫助文檔“Matlab/Getting Started/Programming/Scripts and Functions/Types of Functions”。
4.矩陣及矩陣化編程
矩陣的創建(參考Matlab R2014a幫助文檔“Array Creation and Concatenation”、《MATLAB R2011a教程》第3章p124):
| Function | Description |
| a:b,?a:inc:b | Generating a Numeric Sequence(row vector) |
| ones | Create a matrix or array of all ones |
| zeros | Create a matrix or array of all zeros |
| eye | Create a matrix with ones on the diagonal and zeros elsewhere |
| accumarray | Distribute elements of an input matrix to specified locations in an output matrix, also allowing for accumulation |
| diag | Create a diagonal matrix from a vector |
| magic | Create a square matrix with rows, columns, and diagonals that add up to the same number |
| rand | Create a matrix or array of uniformly distributed random numbers |
| randn | Create a matrix or array of normally distributed random numbers and arrays |
| randperm | Create a vector (1-by-n matrix) containing a random permutation of the specified integers |
矩陣維度信息(參考Matlab R2014a幫助文檔“Array Dimensions”):
| Function | Description |
| length | Length of vector or largest array dimension |
| ndims | Number of array dimensions |
| numel | Number of array elements |
| size | Array dimensions |
| isempty | Determine whether array is empty([ ]) |
| isscalar | Determine whether input is scalar(1x1) |
| iscolumn | Determine whether input is column vector(Nx1) |
| isrow | Determine whether input is row vector(1xN) |
| isvector | Determine whether input is vector |
| ismatrix | Determine whether input is matrix |
矩陣元素索引(indexing,參考Matlab R2014a幫助文檔“Indexing”、《MATLAB R2011a教程》第3章p125):
矩陣的操縱(參考Matlab R2014a幫助文檔“Sorting and Reshaping Arrays”、《MATLAB R2011a教程》第3章p127):
| Function | Description |
| diag | Get diagonal elements or create diagonal matrix |
| repmat | Replicate and tile array |
| reshape | Reshape array |
| flipud | Flip array up to down |
| fliplr | Flip array left to right |
| rot90 | Rotate array 90 degrees |
| [ ],?=[ ] | Empty array(delete) |
| [a, b],?[a; b] | Concatenate arrays horizontally(vertically) |
矩陣索引例子(《MATLAB R2011a教程》第3章p125 例3.2-6):
A=zeros(2,6) A(:)=1:12A =0 0 0 0 0 00 0 0 0 0 0 A =1 3 5 7 9 112 4 6 8 10 12 A(2,4) A(8)ans =8 ans =8 A(:,[1,3]) A([1,2,5,6]')ans =1 52 6 ans =1256 A(:,4:end)ans =7 9 118 10 12 A(2,1:2:5)=[-1,-3,-5]A =1 3 5 7 9 11-1 4 -3 8 -5 12 B=A([1,2,2,2],[1,3,5] )B =1 5 9-1 -3 -5-1 -3 -5-1 -3 -5 L=A<3 A(L)=NaN L =1 0 0 0 0 01 0 1 0 1 0 A =NaN 3 5 7 9 11NaN 4 NaN 8 NaN 12矩陣操縱例子(《MATLAB R2011a教程》第3章p127 例3.2-7、3.2-8):
a=1:8 A=reshape(a,4,2) A=reshape(A,2,4)a =1 2 3 4 5 6 7 8 A =1 52 63 74 8 A =1 3 5 72 4 6 8 b=diag(A) B=diag(b)b =14 B =1 00 4 D1=repmat(B,2,4)D1 =1 0 1 0 1 0 1 00 4 0 4 0 4 0 41 0 1 0 1 0 1 00 4 0 4 0 4 0 4 D1([1,3],: )=[ ]D1 =0 4 0 4 0 4 0 40 4 0 4 0 4 0 4 A=reshape(1:9,3,3) A =1 4 72 5 83 6 9 B=flipud(A) B =3 6 92 5 81 4 7 C=fliplr(A) C =7 4 18 5 29 6 3 D=rot90(A,2)D =9 6 38 5 27 4 1矩陣化編程:
矩陣的邏輯標示法索引方式,和前面提到的算符和表達式的“數組運算”方式結合可以產生強大的“矩陣化”編程方式,用這種方式替代循環結構不僅可以簡化代碼,還可以大大提高代碼執行效率,例子如下。
程序要計算下面的函數:
其中theta在二維下為10/(7*pi*h^2),函數圖像如下所示(類高斯函數):
下面比較普通循環實現和矩陣實現的效率差別:
% file: w1.m function [ out ] = w1(r, h)if nargin==1h = 1;endif 0<=r && r<hq = r/(h/2);theta = 10/(7*pi*h^2);if q<=1out = theta* (1-1.5*q^2+0.75*q^3);elseout = theta* (0.25*(2-q)^3);endelseout = 0;end end % file: w2.m function [ out ] = w2(r, h)if nargin==1h = 1;endtheta = 10/(7*pi*h^2);q = r./(h/2);R = 0<=r & r<h;W = q<=1;out = zeros(size(r));L = R & W;ql = q(L);out(L) = theta* (1-1.5*ql.^2+0.75*ql.^3);L = R & ~W;ql = q(L);out(L) = theta* (0.25*(2-ql).^3); end % file: abc.minc = 0.005; x = -1:inc:1; y = x; t = [];% 循環版本 tic; Z = zeros(numel(x),numel(y)); for i=1:numel(x)for j=1:numel(y)Z(i,j) = w1((x(i)^2+y(j)^2)^0.5);end end t = [t,toc]; disp('循環版本時間'); disp(t(1));% 矩陣版本 tic; [X,Y] = meshgrid(x,y); D = (X.^2+Y.^2).^0.5; Z = w2(D); t = [t,toc]; disp('矩陣版本時間'); disp(t(2));disp('加速比為'); disp(t(1)/t(2)); % 繪制時間圖 figure; bar(t,0.2);運行結果如下:
>> abc 循環版本時間1.9316矩陣版本時間0.0462加速比為41.8445矩陣化編程的一般思路是利用數學上矩陣運算規則、矩陣的數組運算以及bsxfun函數,必要時輔以矩陣操縱。
字符串,Cell數組,Table,Struct:
字符串,Cell數組,Table,Struct本質上都是數組。字符串的元素是char;Cell數組的元素是cell,cell相當于一個容器,其中可以存任意類型,如double型矩陣,字符串,甚至是cell,cell 的內容用{}提取;Table有點像數據庫的表;Struct類似于C語言的結構體。請讀者參考Matlab R2014a幫助文檔“Fundamental MATLAB Classes”。
5.總結及進一步學習
進一步的學習內容可能包括Matlab面向對象編程(類)、GUI編程、Simullink等。我最近有可能會再發一篇“Matlab繪圖基礎”,敬請期待。
參考文獻:
總結
以上是生活随笔為你收集整理的Matlab编程基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记本电脑开机键盘失效
- 下一篇: 粒子群算法学习