CS 30 Review of Matlab for Midterm Test
Mart Molle, Spring 2016
With reference to coverage in the online textbook "Programming in
MATLAB" by zyBooks
Basic Features
Text sections 1.2, 2.1-2.7, 4.10
- The command prompt, ">>", where you can enter commands
one-at-a-time and see the answer. (Note: I will follow the convention
that user-generated input is shown as bold
underline
blue
text, Matlab-generated output is shown in italic, and blank lines are dropped
whenever possible to reduce the length of this document.) e.g.,
>>
2+2
ans=
4
>>
- Multiple commands can be put on one line separated by a comma
(",") or semicolon (";"). A command ending with a semicolon does
not produce any output. Commands can extend across multiple lines by
placing the continuation symbol ("...") anywhere that white space is
allowed (i.e., NOT in the middle of a number or variable name!!), for
example, only the second command generates output:
>>
a = 2+2; b =
7, c = ...
a+b;
b =
7
>> c
c =
11
>>
- Rules for constructing valid variable names and arithmetic
expressions (see p. 6 and 7). Note the distinction between "reserved
words" (such as "for", "while", "end", etc -- see list on page 8)
and pre-defined "special variables" (such as "pi" [== 3.14159], "inf"
[== 1/0, infinity], and "nan" [==0/0, not-a-number]) that are
initialized to some well-known important value but can be changed at
any time to something entirely different under user command. (Beware!)
- Normally, all numbers are represented as double precision
floating point values (i.e., "scientific notation", with a fractional
part and exponent). Integers can be taken care of "for free" by
treating them as a special case where we
essentially fix the exponent to turn the fractional part into a whole
number. The type of value associated with each variable can be
changed at any time, and can be found using the "class" command
>>
x=4;
y=.75;
z='Hello
World!';
>> class(x),
class(y),
class(z)
ans =
double
ans =
double
ans =
char
>>
- Although all numbers are normally stored in double precision
floating point format, you can override this default and specify a
variety of other formats that occupy 8, 16, 32 or 64 bits of memory.
However, since memory is now so plentiful, it
is rarely worth the effort to try to squeeze the data into less space
-- unless you have a huge volume of data (e.g., social security numbers
for everyone in the USA), or you are attempting export or import data
to another application that uses a different format.
- Because floating point numbers cannot store an exact
representation for every real number, the results of a calculation may
differ from what would be expected in pure mathematics:
>>
third=1/3;
if
(2*third)
==
(3*third - third)
'hello'
else
'goodbye'
end
ans =
goodbye
>>
Script M-Files
Text sections 3.1, 3.2, 3.4-3.8 [I will NOT be testing you on custom
functions at this time.]
- A sequence of Matlab commands can be placed in a file (such as
"newcmd.m") using the Matlab editor to create your own multi-step named
command sequences. (Technically, this is called a "macro", rather than
a "function", because executing the command is like pasting the
contents of the file into the command window.) Once the script has been
created and loaded into your workspace (e.g., by selecting "save and
run" from the Editor's debug menu), it can be executed whenever you
want by typing the filename (without the ".m" extension, such as
"newcmd" in this example).
- You can use "echo off" and "echo on" to choose whether or not
Matlab will print the commands within the M-file as if they were being
typed by the user. However the display of the output is not affected by
the setting of "echo" and can be stopped by ending each command by a
semicolon as before.
- Several commands are available to support interaction between the
user and the M-file during execution. For
example
>>
x=input('Enter
the
value
for
x: ')
Enter the value for x: 22
x =
22
>> name=input('What
is
the
name
of your pet? ', 's')
What is the name of your pet? Fido
name =
Fido
>>
- The first argument to the "input" function is a string expression
that will be displayed on the commmand line before waiting for user
input. In the above examples, this argument was a fixed character
string. However, you can construct a customized string by piecing
together different parts within square brackets "[" and "]", like this:
>> name=input('What
is
the
name
of your pet? ', 's')
What is the name of your pet? Fido
name =
Fido
>> weight=input(['Enter
'
name
'''s
weight in pounds: '])
Enter Fido's weight in pounds: 22
weight =
22
>>
- Alternatively, if you just want to provide output without
also waiting for the user to give you an input value, use can use the
"disp" function to display its string argument, or you can use the
"fprintf" function to generated formated output, like this:
>> fprintf('Your
pet
%s
weighs %d pounds.\n', name, weight)
Your pet Fido weighs 22 pounds.
>>
- "fprintf" uses its first argument as a "template" for what the
output line is supposed to look like, but it replaces each "format
operator" (in this example, they are "%s" and "%d", which represent a
string and integer numerical value, respectively) by values obtained
from its other arguments.
Arrays and Array Operations
Text sections 4.1-4.9, 4.12, 5.1, 8.1, 8.2, 8.5-8.9, 9.2, 9.3, 9.6, 9.10
- Matlab is designed as a toolset for manipulating arrays (vectors,
matrices, etc), so it is best to think about all variables as if they
were a two-dimensional table of values (all with a single shared type).
The command "size"
tells you the current number of rows and columns occupied by any object:
>>
size(2+2)
ans =
1 1
>> x
=
22;
>> class(x),
size(x)
ans =
double
ans =
1 1
- Surrounding a list of values
separated by white space and/or commas by a pair of square brackets
"[", "]" is used to construct a row vector. Each time a
semicolon or newline appears within the list, a new row is started. All
rows must have the same number of columns, and if the array elements
are strings then each row must have the same total number of characters.
>> A=[
1,
3
5],
B=[
2 4;5 6]
A =
1 3 5
B =
2 4
5 6
>> class(A),
size(A)
ans =
double
ans =
1 3
>> class(B),
size(B)
ans =
double
ans =
2 2
>> isempty(B)
ans =
0
>> A=[
]
A =
[]
>> class(A),
size(A)
ans =
double
ans =
0 0
>> isempty(A)
ans =
1
>>
- Elements of the array are accessed by specifying their respective
(row, column) locations within the table. Within each dimension (i.e.,
row or column) the numbering scheme always starts with 1 as the first
element, and the the keyword "end" always gives you the last element.
Thus, unless array "A" is empty, "A(1,1)" refers to the element in the
first row, first column, and
"A(end,end)" refers to the element in the last row, last column. More
generally, the row or column subscript can itself be a list (array) of
values, in which case the expression refers to a group of elements from
the array.
>>
C=[1
2
3;
4
5 6; 7 8 9]
C =
1 2 3
4 5 6
7 8 9
>> C(1,1),
C(3,3),
C([1
3],[2
3])
ans =
1
ans =
9
ans =
2 3
8 9
>>
- Another way to construct an array is simply assigning values to
an element. If the element is already part of the array, its value is
updated. Otherwise, the size of the array is expanded to the smallest
(row, column) rectangle large enough to hold all of the assigned values
WITHOUT COMMENT, and the newly-created entries are set to zero. On
the other hand, attempting to access a non-existent element of the
array when evaluating an expression is an error.
>>
M=1,
M(1),
size(M)
M =
1
ans =
1
ans =
1 1
>> M(2)=12
M =
1 12
>> M(3,3)=99
M =
1 12
0
0
0 0
0 0
99
>> M(20,20)
??? Index
exceeds matrix
dimensions.
>>
- The colon is used to construct arrays of sequential values. Two
values separated by a colon constructs an increasing sequence that
starts with the first value and then keeps increasing by steps of one
as long as it is below the second value. Three values separated by two
colons treat the middle value as the step size. Note that the colon
expression does NOT need to be enclosed in square brackets because it
is ALREADY a row vector.
>>
1:4,
pi:2*pi,
4:2
ans =
1 2
3 4
ans =
3.1416 4.1416
5.1416 6.1416
ans =
Empty matrix: 1-by-0
>> 1:2:7,
10:-5:0
ans =
1 3
5 7
ans =
10 5 0
>> if
1:4
==
[1:2,
[3 4]], 'yes', else, 'no', end
ans =
yes
>>
- The colon operator can also be used to generate ranges of
subscript (similar to cell addressing in Microsoft Excel spreadsheets)
in order to access (parts of) an array. Furthermore, a single colon
(with no values before or after it) has a special meaning when used as
an array subscript, namely a shortcut for the expression "1:end" that
represents the entire range of values for that dimension.
>>
C=[1
2
3;
4
5 6; 7 8 9]
C =
1 2 3
4 5 6
7 8 9
>> C(:,1),
C(1,:)
ans =
1
4
7
ans =
1 2 3
>> if
C(1:end,1)
==
C(:,1),
'yes', else, 'no', end
ans =
yes
>>
- An array reference with a single colon has a special meaning, no
matter what the size or shape of the array: form all elements
from the array into a single column, with column 1 on top and column
end on the bottom. More generally, for an array of any size or shape,
you can access its elements through one-dimensional array references
instead of the usual (row,column) form. In this case, we call the
resulting value(s) an array index,
rather than an array subscript,
and
interpret
them
as positions in the "single colon" version of the
array. (The zyBooks text, section 8.2 calls this feature linear indexing.)
>>
C(:)
ans =
1
4
7
2
5
8
3
6
9
>> C(4)
ans =
2
>> C(4:6)
ans =
2
5 8
>> A=[1
3
5],
A(:)
A =
1 3 5
ans =
1
3
5
>>
- Arithmetic and/or logical expressions are extended to arrays in
two different ways. First, scalar operations (such as "+" or ">")
apply the same formula independently to each element of the array. In
this case, the two arguments must have exactly the same size and shape.
However, if one of the arguments is a scalar (single) value it will be
automatically expanded to the required size with duplicate copies of
the scalar value.
>>
C,
C+1
C =
1 2 3
4 5 6
7 8 9
ans =
2 3 4
5 6 7
8 9 10
>> D=[2
3
4;
9
8 7; 1 1 9]
D =
2 3 4
9 8 7
1 1 9
>> C+D
ans =
3 5 7
13 13 13
8 9 18
>> C>D,
C==D
ans =
0 0 0
0 0 0
1 1 0
ans =
0 0 0
0 0 0
0 0 1
>>
- The alternative is vector (or matrix) operations, the simplest of
which is matrix multiplication. In order to calculate C=A*B, the number
of columns
in A must match the number of rows in
B, and the dimension of C will be the number of rows
from A and number of columns
from B. In this case, C(i,j) is the sum of all terms obtained by
multiplying each element from A(i,:) by the corresponding element from
B(:,j).
>>
A=[1
2
3],
B=[4,
5; 6 7; 8 10]
A =
1 2 3
B =
4 5
6 7
8 10
>> A*B
ans =
40 49
>> B*A
%
shapes
don't
match
??? Error
using ==> mtimes
Inner matrix
dimensions must agree.
>> B*B'
ans =
41 59 82
59 85 118
82
118 164
>> B'*B
ans =
116 142
142 174
>>
- The "find" function returns the locations within a matrix
expression where there are non-zero (ie. "true") values. BEWARE that
the results generated by "find" are in the "single colon"
one-dimensional column index form, UNLESS the result is assigned to an
array constructed from the names of two variables!!!
>>
D,
D(:)
D =
2 3 4
9 8 7
1 1 9
ans =
2
9
1
3
8
1
4
7
9
>> find(D==9),
[r,c]=find(D==9)
ans =
2
9
r =
2
3
c =
1
3
>> D(2),
D(9),
D(2,1),
D(3,3)
ans =
9
ans =
9
ans =
9
ans =
9
>>
- For functions like "find", which generates a variable number of
solutions in an array, it is important to know how to classify the
result as a "success" or "failure". Matlab provides several ways to
determine the number of results generated, including "size", "length",
"numel" and "isempty". However, interpretting the answers can be tricky
because Matlab's representation of an empty array is inconsistent
between a zero-element array (i.e., "[ ]", which has zero rows and zero
columns) and a sequential array that ends before it begins (i.e.,
"4:2", which has one row and zero columns). I think "isempty" and
"numel" seem to cover most situations with the fewest surprises....
>>
D=[2
3
4;
9
8 7], isempty(D), size(D), size(D,1), size(D,2), length(D),
numel(D)
D =
2 3 4
9 8 7
ans =
0
ans =
2 3
ans =
2
ans =
3
ans =
3
ans =
6
>> D=D(:),
isempty(D),
size(D),
size(D,1),
size(D,2), length(D), numel(D)
D =
2
9
3
8
4
7
ans =
0
ans =
6 1
ans =
6
ans =
1
ans =
6
ans =
6
>> D=[
],
isempty(D),
size(D),
size(D,1), size(D,2), length(D), numel(D)
D =
[]
ans =
1
ans =
0 0
ans =
0
ans =
0
ans =
0
ans =
0
>> D=4:2,
isempty(D),
size(D),
size(D,1),
size(D,2), length(D), numel(D)
D =
Empty matrix: 1-by-0
ans =
1
ans =
1 0
ans =
1
ans =
0
ans =
0
ans =
0
>>
Character Strings
Text sections 2.9, 4.11, 7,1, 7.2, 7.5, 7.6 [we did NOT cover the "sscanf" function, but
we did do "eval"]
We covered "strvcat" for making 2D arrays of characters but NOT the
material of section 7.7
- In Matlab, a string is a sequence of characters between single
quotes, and it can be manipulated just like a one-dimensional row
vector. In other words, strings can be concatenated by enclosing them
between a pair of square brackets, and pieces from the string can be
selected and/or changed using array references.
>>
Name='John
Doe',
size(Name),
Name(6:8)='Foo'
Name =
John Doe
ans =
1 8
Name =
John Foo
>> Name(2:3)=[]
Name =
Jn Foo
>>
- Since strings are implemented as one-dimensional character
arrays, it is not possible to construct a row-vector of strings because
the square brackets will simply concatenate them into a single string.
(Of course, a cell array can easily handle strings as the contents of
each cell -- but that adds an extra layer of complexity!) On the
other hand, enclosing a series of strings separated by semicolons
between square brackets will create a column-vector of strings -- but
it is awkward to use because the requirement that the dimensions of all
arrays must be rectangular forces all of the strings (i.e., rows) to
have the same length. Matlab provides the "char" and "strvcat"
functions to take care of extending all strings to the maximum length.
- Note the distinction between the numeric code that is used to
represent each character of an (extended) alphabet, versus the numeric
value corresponding to a string of digits.
>>
double('a'),
char(97)
ans =
97
ans =
a
>> double('97'),
char(a)
ans =
57 55
??? Undefined
function or variable 'a'.
>>
- A different set of functions is required to convert back and
forth between a string of digits and the corresponding number, such as
"num2str", "str2num", etc.
>>
num2str(2),
num2str(pi),
class(ans)
ans =
2
ans =
3.1416
ans =
char
>> str2num('22.5'),
str2num('-1'),
class(ans)
ans =
22.5000
ans =
-1
ans =
double
>>
Relational and Logical Operations
Text sections 2.10, 4.5, 5.2, 5.3, 11.1, 11.4 Somehow the text doesn't
seem to mention "&&" and "||"
- Relational operators are used to make comparisons between two
values (see the table on page 189). Note that the comparison for
equality uses "==" because a single equal sign is already being used
for the assignment statement, and that not equals uses "~=" (as opposed
to "!=" in C). The result of a comparison is either "true" (indicated
by a non-zero value, usually 1) or "false" (indicated by zero).
- The results of several comparisons can be combined using logical
operators, AND, OR or NOT (represented by "~"). In Matlab, AND and OR
come in two different flavors: "&&" and "||" use lazy evaluation, where the second
operand is ignored if the result is completely determined by the first
operand, whereas "&" and "|" evaluate both operands whether they
need to or not.
Control Flow
Text sections 11.1, 11.3, 11.5, 12.1-12.6
- "if" statements provide a means for selecting which commands to
execute based on the value ("true" or "false") of a condition. Every
"if" has a matching "end", so any number of commands can be included
within its body, to be executed if the condition is "true". "elsif" and
"else" parts are optional.
- At most one group of commands will be executed from each "if"
statement, namely those directly below the first "if" or "elsif" for
which the condition is "true", if any. Otherwise, it will be the
commands below the "else", if there is one.
- "while" and "for" statements provide a means for repeated
execution of the commands in the loop body (down to the matching
"end").
- "while" loops have a condition at the top. If the condition is
true when we check it at the top of the loop, we execute the entire
loop body before checking the condition again, and so on indefinitely
until the condition becomes false.
- "for" loops specify a list of values for the index variable. At
the top of the loop, the index variable is assigned to the next value
from the list (if any), and then we execute the entire loop body before
updating the value of the index variable again. Note that Matlab uses
an array to represent the list of values for the index variable in a
for loop, and if the array is two-dimensional then the index variable
is assigned to the columns of the array, one at a time.
- The "break" command can be used to force an early exit from the
nearest enclosing "while" or "for" loop.
- The "continue" command can be used to jump to the bottom of the
nearest enclosing "while" or "for" loop. In other words, you skip the
rest of the statements inside the loop body. However, you do NOT exit
the loop completely (the way you do with "break") and so go back up to
the top and retest the condition for a "while" loop or advance to the
next value of the index variable.
Cell Arrays and Structures
Text sections 14.1-14.7. 14.9
- The primary feature of a cell array (as opposed to a "plain"
array) is that every element can have its own class. You can create a
cell array from a list of elements by enclosing it between a pair of
curly braces "{", "}". Just like "plain" arrays, elements within the
same row are separated by commas or white space, and every newline or
semicolon indicates the start of a new row.
>>
Bag={2,
'Hello
World';
[1 2; 3 4] pi}
Bag =
[ 2]
'Hello World'
[2x2
double] [ 3.1416]
>> class(Bag)
ans =
cell
>>
- The curly braces also play a special role when accessing the
elements of a cell array. Enclosing subscripts in parentheses is used
to specify cells (i.e., the containers), whereas enclosing the
subscripts in curly braces specifies their contents (i.e., the data
inside those cells).
>>
Bag(2,1),
class(Bag(2,1))
ans =
[2x2 double]
ans =
cell
>> Bag{2,1},
class(Bag{2,1})
ans =
1 2
3 4
ans =
double
>>
- Since the contents of different cells is unrelated, in
terms of both class and size, cell arrays are particularly useful for
creating arrays of strings. This is because strings are just 1D vectors
of characters, so it is impossible to make a row vector strings (all
the characters just merge to form a single string), and you cannot make
a column vector of strings (which is really a 2D array of characters)
unless all the rows are the same length.
>>
animals
=
{'lion' 'leopard'; 'ox', 'waterbuffalo'}
animals =
'lion'
'leopard'
'ox'
'waterbuffalo'
>>
- Notice that Bag{2,1} i.e., the contents
of the cell container in row
2, column 1 of the cell array, is itself an ordinary 2D array of
doubles. Thus, I can select a specific element or group of elements
from that ordinary array by adding a further level of array indexing
using regular parentheses, as if
Bag{2,1} was the name of an ordinary 2D array. The zyBooks text
discusses this distintion in section 14.3, where it uses the
terminology cell display indexing
versus cell contents indexing.
Here
is an example showing how to use curly braces and regular
parenthesis, one after the other, to access part of the contents of a
cell:
>>
Bag{2,1}(1,2),
Bag{2,1}(:,2)
ans =
2
ans =
2
4
>>
- Since Bag(1,1) is one cell from an array of cells, any value
assigned to it must itself be a cell, whereas is contents Bag{1,1} can
hold anything. Just like a "plain" array, assigning a value to a
non-existent cell causes the boundaries of the array to expand.
However, the newly created cells are initialized to empty lists ("[ ]")
rather than the number zero.
>>
Bag(1,1)={[2
4]}
%
construct a cell and place it somewhere in a cell array
Bag =
[1x2
double] 'Hello World'
[2x2
double] [ 3.1416]
>> Bag{1,1}=1/4
%
construct a non-cell value and use it as the contents of a cell
Bag =
[ 0.2500] 'Hello World'
[2x2
double] [ 3.1416]
>> Bag(1,1)=0
%
construct a non-cell value and place it somewhere in a cell array
??? Conversion to cell from double
is not possible.
>> Bag{4,1}=12
%
construct a non-cell value and place it somewhere in a cell array
Bag =
[ 0.2500] 'Hello
World'
[2x2 double]
[ 3.1416]
[]
[]
[
12]
[]
>>
- A structure array consists of multiple elements, called fields, that may have different
data types and are identified by their respective field name, rather
than a numeric index or subscript. New fields can be added to a
structure at any time, merely by appending a dot followed by the new
field name to the array. The overall structure, or any of its fields,
can be turned into arrays by adding a subscript or index.
>>
clear
s;
s(1).height=4;
s(2).vec(1)=1;
s(2).vec(2)=5;
s(1).name=’Fred’;
s(1).vec=[7
13];
s(2,2).height=8;
disp(s)
2x2 struct array with fields:
height
vec
name
>> size(s)
ans =
2 2
>>
Functions
Text sections 3.3, 13.1, 13.3-13.5, 13.8-13.9
- Matlab "custom functions" (i.e., those you construct yourself, as
opposed to those built in to Matlab) are very similar to script m-files:
- They consist of named
sequences of Matlab commands stored in a file.
- You must choose a name for each of your command sequences, such
as TryMe. Once you have
constructed such a command sequence, Matlab to execute that command
sequence whenever you type its name.
- The file name is the same as the command sequence name, except
that it is extended adding ".m" to the end, such as TryMe.m in this example.
- This requirement is not
true for sub-functions, which
are written another function in the same file. Sub-functions can only
be called by other functions whose definition is part of the same file,
since Matlab only knows how to find functions that are stored in files
having the same name.
- Executing a command sequence means temporarily stopping execution at
the place where its name was called, going through the command sequence
in the file, then resuming execution
at the place where its name was called.
- However, there are several important differences between scripts
and functions:
- A script executes in the same workspace environment as the
place where its name was called (typically, the "base" workspace for
the Matlab command window), whereas a function executes in its own
private workspace.
- A script shares all variables with the calling environment.
If a script carries out the assignment x=0;
then that variable assignment will still be visible when execution
resumes afterwards.
- All variables you can touch inside a function are local to
that function. You cannot access any variables from the calling
environment, and any variables created during the function execution
disppear when execution resumes afterwards.
- Only functions can have arguments,
which are used for passing values back and forth between the function
and its calling environment.
- The arguments are defined on the first line of the function
definition, like this:
function
[a, b] = TryMe (c, d)
- To the left of the equal sign is a vector of output arguments (in this case, a and b). These will be treated as
variables within the function and their final values will be returned
to the calling environment.
- To the right of the equal sign is a list of input arguments (in this case, c and d). These will be treated as
variables within the funcation and their initial values are obtained
from the function call. Note that it doesn't matter whether the
function call uses variable names or expressions to supply the values
for the input arguments -- either way, only the values are passed into
the function. Thus if the first input argument in the function call was
some variable x in the calling
environment, your function cannot affect the value of that variable x from the calling environment by
changing the value of its local variable c.
- Matlab does not consider it a mistake when a function call
does not supply values for all of its arguments. You can use the
read-only variables nargin and
nargout to determine
how many arguments you actually received.
- A function handle is
a special class of variable that allows us to pass a method of calling one function as an
input argument to
another function, allowing the second function to make calls to the
first function. For example, UseMe=@cos;
creates a method of calling the cos
function, which can be passed as an input argument to the Matlab
function fminbnd (UseMe, -1, 3)
so it can find the minimum value for the function cos(x) within the inteval -1<=x<=3.
- An anonymous function
is one that can only be accessed through a function handle, and has no
separate life of its own (as a named function stored in its own file).
Note that the "content" of the function can be any expression you could
write on the right-hand side of an assignment statement, like this:
ghost
= @(x) 5*x - sqrt(x);