Sunteți pe pagina 1din 11

Notes on MATLAB programming (Earlier versions of this page were titled /MATLAB as a programming language/) Jonathan Jacky <index.

html>, Apr -- Aug 2006 begun, unfinished topics end with |...|, Mar 2007 fill in some topics, minor tweaks, June 2007 fill in biquad example, fix matlab-numpy link, Mar 2008 Separate Commands section, add plot commands. -----------------------------------------------------------------------I recently learned MATLAB to design and analyze digital filters for a project <http://staff.washington.edu/jon/gr-mrfm/> (also here <http://lists.gnu.org/archive/html/discuss-gnuradio/2005-01/msg00232.html> and here <http://www.research.cornell.edu/KIC/events/MRFM2006/pdfs/Jacky%20talk/jacky-tal k.html>). You can get a lot of work done in MATLAB without programming. Nevertheless, its programming language has some unusual features, particularly regarding matrices <#matrices> and persistence <#persist>. It also provides most of the facilities of a conventional language, so you can program in a familiar style if you wish, but you can often do much better if you take advantage of its unique features. The MATLAB programming language and IDE support an ad-hoc programming style where it is easy to turn the useful parts of an interactive session into a program <#structure>. This page is not intended to be a reference or even a summary of MATLAB, for that see the references <#ref>. Instead, I point out some important differences from other languages, that I expect will be interesting to programmers and useful for newcomers. REPL <#repl>, Commands <#commands>, Program structure <#structure>, Data types <#types>, Matrices <#matrices>, Exceptions <#except>, Persistence <#persist>, Large systems <#large>, Alternatives <#standard>, References <#ref> REPL and IDE Invoking MATLAB usually starts a read-evaluate-print loop (REPL). You type an expression, statement, or command at the command prompt |>>|, and MATLAB prints the result (if there is one), or executes some side effect such as displaying a graph. Invoking MATLAB usually starts an Integrated Development Environment (IDE) that includes a window for the REPL, editor windows for writing code, a command history window, a file system browser etc. Random mouse motions can cause the panels in the IDE to scatter like leaves before a storm. To restore them, use the main panel menu bar: |Desktop -> Desktop Layout -> Default|. The REPL makes it easy to do ad-hoc calculations and plotting. The MATLAB programming language and IDE make it easy to turn the useful

parts of a REPL session into a program <#structure>. You can also run MATLAB without the IDE in a terminal window. |matlab -h| Print command line options |matlab -nodesktop | Run in terminal with no IDE |matlab -r /command/| Start MATLAB, execute |/command/|, remain in REPL unless |/command/| ends with |exit| You create a variable just by assigning to it. There are no variable declarations. You can assign values of different types to the same variable. Be warned that MATLAB will happily and silently allow you to reassign variables that it initially assigns, such as |pi| and |i|. I haven't found any way to define a constant. Scripts and functions in the filesystem are loaded implicitly, just by naming them. There is no command to load or import code. The |load| command is used for persistence <#persist>. Three dots |...| at the end of a line continues the command on the next line, like backslash |\| in the Unix shells or Python. An optional semicolon |;| at the end of a command is not a a terminator or separator. Instead, it suppresses printing the result. You often want this, especially when the result is some huge array. Identifiers are case-sensitive. |A| is different from |a|, etc. It is confusing that |help| output shows function and command names in capitals. If you type them in that way, they will not work. Array indexing begins at 1, not 0 as in most programming languages. Use single quotes for strings: |'abc'|, etc. You can't use a hyphen |-| in an indentifier. MATLAB thinks it's a minus sign. Use an underscore |_| instead. The variable |ans| stores the value computed by the last command (the "answer"), so you can use it in the next one. You can use wild cards in variable names in commands where that makes sense, for example |whos x*| and |clear x*|. Commands Here are some useful commands for interacting with the REPL. There is a much larger command summary here <http://mathesaurus.sourceforge.net/matlab-numpy.html>. Many commands have several variants with the same name but different argument lists and return values, so it is a good idea to consult |help| about any command you use. |ver| Print information about version and license, including all installed toolboxes |help /command/| Print information about |/command/| (including functions and scripts).

|which /command/| Print |type /command/| Print |lookfor /com/| Print contains the string |/com/|. |help +| (or any other and special characters.

full path to source file for |/command/|. source code for |/command/|. list of commands whose name or brief description operator) print information about all operators

|format compact| Print fewer blank lines, to fit more on the screen. |format long| Print lots of digits in results, |format short| for few. |A = |t = |y = Here |y| 2048| Assign scalar |2048| to variable |A| 0:0.1:2*pi| Assign vector |[0.0 0.1 0.2 .. 6.2 ]| to variable |t| A*sin(t) + A| Assign vector of function values to variable |y|. |*|, |+|, and |sin| are /vectorized/. Print vector |y|

|who| List all user-defined variables |whos| List all user-defined variables, along with their sizes and types ("classes") |clear all| Remove all user-defined variables, to avoid confusion from previously assigned values. |plot(y)| Plot values of |y| as a function of index (in this example x axis ranges from 1 .. 63) |plot(t,y)| Plot values of |y| as a function of |t| (here x axis ranges from 0.0 .. 6.20) |plot(y, sqrt(y))| Plot values of |sqrt(y)| as a function of values of |y| (here x axis ranges from 0.0 .. 4096.0) |plot(t,y/100, t,sqrt(y))| Plot both |y/100| and |sqrt(y)| as functions of |t| on the same plot |figure| Create new figure to show output of subsequent plot commands, to preserve previous figure. |hold on| Make subsequent commands plot on the same figure, without clearing plots already displayed there. |/h/ = figure| Create new figure, return figure handle /h/. |figure(/h/)| Make figure /h/ the current figure (or just bring figure /h/ to the top using the window manager). |close(/h/)| Delete figure /h/. |close all| Delete all figures, to unclutter the screen. |!/command/| MATLAB). Execute /command/ with system command interpreter (not

Program structure M-files <#mfiles>, Scripts <#scripts>, Functions <#functions> M-files MATLAB source code must be stored in files with the |.m| extension, called /M-files/. Every M-file defines one MATLAB command (a statement or a function). The name of the command is the file name (without the |.m| extension). When you invoke a command (at the REPL or in another M-file), MATLAB searches a path for an M-file with that name, and executes it. There is no separate command to import or load an M-file.

You can't use a hyphen |-| in the name of an M-file. MATLAB thinks it's a minus sign. Use an underscore |_| instead. It is the convention that the first comment line in |/command/.m| has the form |/%COMMAND/ one-line description of /command/ ...| for example |%BIQUAD make cascaded biquad filter, return coeffs for 2nd order sections| The IDE file browser displays this line, and some REPL commands use it: |help /command/| Print first block of comment lines in |/command/.m| |lookfor /com/| Print first comment line in each M-file whose name contains the string |/com/|. Functions local to an M-file with |@| |...| There are two kinds of M-files, /scripts/ and /functions/. Scripts A script defines a command with no arguments and no return values. It is just a sequence of MATLAB commands (and comments). Invoking a script executes those commands, exactly as if they were typed at the REPL (or invoked in the script that invoked the command). All variables in a script are global; they can be used and assigned in the REPL session (or script) that invoked the script. MATLAB encourages an ad-hoc programming style where you first experiment by typing commands at the REPL, then create a script by saving the sequence of commands that worked. The MATLAB IDE supports this by providing a command history window, from which commands can be cut and pasted into an editor window. Functions A function defines a command that may take arguments and return values. Here are the first few lines of biquad.m: function [Hsosm,sosm] = biquad(bd,ad,frac_bits,gain) %BIQUAD make cascaded biquad filter, return coeffs for 2nd order sections % ... other comment lines describe inputs, outputs, etc. ... H = dfilt.df2(bd,ad); Hsos = H.sos; sosm = Hsos.sosmatrix; ... more code follows ... The name of the function must be the same as the file name. Notice that there are no data types mentioned in the declaration. Functions can return multiple values, as in the previous example. That function could be called like this:

>> bd = ... >> ad = ... >> [Hsosm,sosm] = biquad(bd, ad, 14, 1.0) The brackets on the left hand side of this assignment might suggest that there is a tuple data type, but apparently there is no such thing; this is special syntax for function return values only. In general, |[n,x,s] = ...|, where the right hand side is not a function call, does not work. There is no |return| statement. After the last statement in the function executes, the function exits and the values of all the variables whose names appear on the left side of the function declaration are returned. Variables in a function are local. MATLAB encourages an ad-hoc programming style where it is easy to turn a script (or part of a REPL session) into a function. Simply add a declaration at the top that defines the name and identifies which variables are the parameters and which store the return values. You can ignore returned values. It is not an error to assign fewer variables than the function returns, or to assign no variables at all. Functions can have optional arguments. Within each function you can use |nargin|, the number of arguments the function was called with, for example biquad.m (above) contains ... if nargin < 3 frac_bits = 14; % default end ... There are no keyword arguments. MATLAB functions often achieve the same effect by using pairs of optional arguments, where the first of each pair is a string <#strings> (the keyword), and the second is the value. Function arguments with |@ ..., | earlier scheme with strings |...| Function names can be overloaded, with different parameters and return values |...| Vectorization <#vectorize> requires care. The problem seems to be that the |if| statement is not vectorized - apparently |if| always treats the conditional expression as a scalar. If matrix elements are subject to conditionals, so that different elements might take different paths, this is the one circumstance where you must iterate. |...| Data types MATLAB calls data types "classes". The |whos| command shows the classes of all of your variables. There are no scalar classes. Scalars are a special case of matrices <#matrices>: matrices with one element. Numbers <#numbers>, Booleans <#bool>, Strings <#strings>, Objects <#objects>

Numbers All numbers are stored as double-precision floating point values. Usually, many more digits are stored than are printed. The functions |round|, |floor|, |ceil|, and |fix| return the integer nearest to a number by various criteria. Complex numbers are entered (and printed) as in |1 + 2i| (or |1 + 2j|). Extract the components of a complex number with the functions |real| and |imag|, find the magnitude and phase with |abs| and |angle|. The variables |i| and |j| are initially assigned (by MATLAB) to the imaginary constant |0 + 1i|. This can be confusing because you (or scripts you use) often assign them to something else. Use |1i| instead. There is an initially assigned variable |pi| but not |e|. Use |exp(1)| instead. Booleans There is no Boolean type. MATLAB documentation refers to the /logical/ (not Boolean) values 0 (false) and 1 (true), which are returned by logical operations. Any nonzero value is interpreted as true when it appears as an operand of a logical operation. Strings MATLAB is not known for text processing, but it has a string data type. The command |lookfor string| shows what functions are available. Use single quotes for strings: |'abc'| Strings are used in printed output, and to put labels and captions on graphs. There are |fprintf| and |sprintf| functions like in C, with the usual format strings, escape characters, etc. However, if there is an array argument, the corresponding format string is applied to every element, printing out the whole array. Printing large arrays, with control over the layout of rows and columns, is one of the rare MATLAB operations where I have found it helpful to code loops. Strings are often used as symbols. Many functions use particular strings as arguments to select options. For example, the |gensig| signal generator function uses the strings |'sin'|, |'square'|, or |'pulse'| to select the waveform type. |eval ...| Strings are actually 1-dimensional arrays of characters, characters are 1-element arrays. All the usual matrix operators apply.

Handles Plot handles |...| Function handles |...| Objects Objects and dot notation |...| Examples from filter toolbox |...| Matrices Vectorization <#vectorize>, rows vs. columns <#dim>, constructors <#construct>, accessors <#access>, assignment <#mat-assign> An array is called a /matrix/. A one-dimensional array is a /vector/. Matrices and vectors are central in MATLAB; most of the unusual features in the language concern them. They are very easy to work with. It is rarely necessary to code loops in order to use them, as we shall see. MATLAB itself uses arrays wherever it can. Strings are vectors of characters. The ranges in iterations are arrays. In a loop that begins |for x = v ...|, the index variable |x| iterates over the elements of vector |v|; in |for x = A ...|, |x| iterates over the columns in the matrix |A|. (But loops appear only rarely in MATLAB programs). Vectorization, array and matrix operations, reductions Many operators and functions are /vectorized/: they work on every element in a vector or matrix. It is not necessary to use any "map" function to achieve this. For example, assign |x = pi/2|, then |sin(x)| evaluates to |1|, as usual. But also assign |v = [ 0 pi/6 pi/2 ]|, then |sin(v)| evaluates to |[ 0 0.5 1.0 ]|. Some MATLAB statements are also vectorized. The statement |fprintf('%8.3f', A)| prints every element in the matrix |A| with the specified format. Some binary operators are applied element-by-element in the obvious way. For example, if |A| and |B| are matrices, the sum |A+B| is the matrix of their element-by-element sums. This requires that |A| and |B| have the same number of dimensions and the same size in each dimension. Otherwise, this expression raises the error |Matrix dimensions must agree|. Operators that work element-by-element are sometimes called /element-wise/ operators, /pointwise/ operators, or /array operators/. Some binary operators are not simply applied element-by-element. Instead they have their traditional meaning from mathematics. For example, |*| is matrix multiplication and |^| is matrix power. These are called /matrix operators/ to distinguish them from the element-by-element array operators.

For every matrix operator, there is also a corresponding element-wise array operator. For example, the array operators for multiplication and power are |.*| and |.^| (notice the leading dot). When one of the operands is a scalar, you do not have to use the array operator. For scalar |c|, |c*A| (or |c+A| etc.) computes the products (or sums etc.) element-wise. In this context, MATLAB treats |c| as a mathematical scalar, not a one-element matrix (which would have the wrong size for this matrix multiplication). Some functions are /reductions/ that compute a scalar from a vector. They include |sum|, |prod|, |max|, |min|, |mean|, and |std| (standard deviation). Reductions applied to 2-D matrices return a vector of the results of applying the reduction to each column. Relational and logical operators can also take matrix operands. For example, |A > 10| or |A > B| etc. evaluates the Boolean expression element-wise, and returns the matrix with the logical values |1| (true) at the elements where the expression is true, and |0| (false) elsewhere. The Boolean reductions |all| and |any| act as logical quantifiers; they return 1 or 0 (true or false) to indicate whether all or any of the elements are nonzero (true). Also, |find(A)| returns the vector of linear indices of nonzero (true) elements in |A|, and |find(A > 10)| etc. returns the vector of indices where the Boolean expression is true. The vector of indices can then be used to access <#access> or update <#mat-assign> those matrix elements. The command |help *| (or any other operator symbol besides |*|) prints information about all the matrix and array operators. Vectorization, array and matrix operators, and reductions contribute to making loops mostly unnecessary. Dimensions, size, rows vs. columns Scalars are matrices. Every scalar can be treated as a matrix of one element, with as many dimensions as needed in context. For example, assign |a = 42|, then evaluate |a(1)|, |a(1,1)|, |a(1,1,1)| etc. Therefore, no special operator or function is needed to extract a scalar from a one-element matrix, or to concatenate a scalar to a vector. There are two kinds of one-dimensional arrays. Like mathematics but unlike most programming languages, MATLAB distinguishes between row vectors and column vectors. Built-in functions and toolboxes use the conventions of the application domain. For example, time series are column vectors, polynomial coefficients (including digital filter coefficients) are row vectors, and polynomial roots are column vectors. Even vectors are considered to have two dimensions: row vectors are 1 x N matrices, column vectors are N x 1 matrices, for example try |v = [ 1 2 3 ]| then |size(v)|. The distinction between row and column vectors is significant for some operators and statements. For example, given the 1 x N row vector |vr| and the N x 1 column vector |vc|, |vr*vc| is the /inner product/ or /dot product/, a scalar, but |vc*vr| is the /outer product/, an N x N matrix.

The matrix transpose operator, apostrophe |'|, creates a row vector from a column vector and vice versa. Given row vector |vr|, the assignment |vc = vr'| creates column vector |vc|. The function application |ndims(A)| returns the number of dimensions in matrix |A|, and |size(A)| returns the size of each dimension, in an array of length |ndims(A)|. The reduction |prod(size(A))| returns the total number of elements. The index of the first element in each dimension is |1| and the index of the last element is |end|. Constructors Construct row vectors using spaces or commas: |vr = [ a b c ]| or |vr = [ a, b, c ]|. Construct column vectors using semicolons: |vc = [ x; y; z ]|. Combine both to construct matrices: |A = [ a11 a12; a21 a22 ]|. The entries in matrix constructors can be expressions with scalar or matrix values. You can use these constructors to build up large matrices, concatenate matrices, append scalars to vectors, etc. The functions |ones|, |zeros| (note spelling), and |random| construct matrices where all the elements are |1|, |0|, or values drawn from a specified random distribution. Consult |help| about specifying sizes, etc. These functions can be used to pre-allocate arrays in order to use storage efficiently. Range expressions (using the range operator, colon |:|) construct vectors, given an initial value and a final value: |v = 1:10|. Range expressions can include an optional increment: |v = 1:2:10| and can use fractional values: |v = 0.3:-0.15:-0.45|. Range expressions are frequently used to code loops: |for i = 1:n ...|. The variety of constructors contributes to making loops mostly unnecessary. Accessors Use subscripts to access scalar matrix elements: |x = A(i,j)|. Indexing begins at 1, not 0 as in most programming languages. The index of the last element in a given dimension is |end|. You can use it in expressions: |v(end - 1)| etc. Use ranges to access sub-matrices: |B = A(k:l,m:n)|. Subscripts and ranges can be built from any integer-valued expressions. When ranges are used as accessors, they cannot include fractional values. A range operator without operands ranges over all the accessible elements; |vr = A(3,:)| accesses the entire third row. Notice that |:| is an abbreviation for |1:end| (but |i:| or |:j| is not allowed). A vector of indices |v([i,j,k])| returns the vector of elements at those indices, the same as |[ v(i) v(j) v(k) ]|. (Using ranges as accessors is a special case of this). Recall that the |find| function returns a vector of indices.

Use a single /linear index/ as in |A(3)|, |A(3:7)|, or |A(:)| to access any matrix one element at a time, as if it were a vector, with the elements indexed by row first (scanning down columns), so |A(1)| is |A(1,1)|, |A(2)| is |A(2,1)| etc. Also, |A(:)| is the entire matrix /flattened/ to a column vector. The variety of accessors contributes to making loops mostly unnecessary. Assignment and mutability Matrices are mutable. You can assign new values to individual elements, sub-matrices, and selected elements by using indices, ranges, or vectors of indices: |A(i,j) = x|, or |A(i,:) = v|, or |A([i,j,k]) = [ x y z ]| etc. Matrices are mutable, but most matrix operations return a new matrix, rather than updating their operands in place. For example, |A'| or |c*A| etc. does not change |A|. This makes it easy to program in a functional style. Assigning a matrix to a variable creates a new copy of a matrix; it does not create an alias. The copy can be updated without changing the original: after |A = [ 1 2 3 ]| then |B=A| then |B(2)=4|, the matrices |B| and |A| differ. This is unlike many programming languages, where assigning an array to a variable creates an alias, and updating either |A| or |B| would change both. You can grow a matrix by appending in a constructor, or assigning to new elements (with higher indices) but that can be quite slow. It is much faster to pre-allocate storage by initially constructing a matrix of the needed size, if that is known. Persistence You can easily save and restore the state of MATLAB session: the variables and their values. You can save and restore individual matrices |...| |load, store, dlmwrite ...| Exceptions Warnings that print messages vs. errors that stop execution |...| Large systems Quantum optics toolbox <http://www.qo.phy.auckland.ac.nz/qotoolbox.html> |...| MATLAB itself |...| Alternatives Octave <http://www.gnu.org/software/octave/>, open-source MATLAB clone.

How complete? |...| NumPy <http://mathesaurus.sourceforge.net/matlab-numpy.html>, IDL, PDL, etc. have MATLAB-like array operations |...| References Command summary (NumPy also) http://mathesaurus.sourceforge.net/matlab-numpy.html I learned what I know about MATLAB by reading (a little) in these sources, in roughly this order. James H. McClellan, Ronald W. Shafer, and Mark A. Yoder, /DSP First: a Multimedia Approach/, Prentice Hall 1998 (especially, but not only, Appendices B and C.1) Sze M. Tan, A Computational Toolbox for Quantum and Atomic Optics http://www.qo.phy.auckland.ac.nz/acols98b.pdf Some useful Matlab tips (some tips but mostly links) http://www.cs.ubc.ca/~murphyk/Software/matlab_tips.html Getting Started with MATLAB http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/getstart.pdf Signal Processing Toolbox User's Guide http://www.mathworks.com/access/helpdesk/help/pdf_doc/signal/signal_tb.pdf MATLAB Programming http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matlab_prog.pdf Daniel T. Kaplan, /Introduction to Scientific Computation and Programming/, Brooks/Cole 2004 (teaches MATLAB as a general-purpose programming language) Matlab tips and tricks (haven't read this yet, but looks useful) http://www.ee.columbia.edu/~marios/matlab/matlab_tricks.html Mathworks online documentation http://www.mathworks.com/access/helpdesk/help/helpdesk.html http://www.mathworks.com/support/tech-notes/list_all.html http://www.mathworks.com/company/newsletters/digest/pastissues/index04_06.html, for example sept01/matrix.html <http://www.mathworks.com/company/newsletters/digest/sept01/matrix.html>

S-ar putea să vă placă și