Introduction to Matlab, MSc in Robotics Contents

advertisement
Introduction to Matlab, MSc in Robotics
Contents
Prerequisites ........................................................................................................................................... 3
Course description .................................................................................................................................. 3
Description of Matlab ............................................................................................................................. 3
General tips in using Matlab ................................................................................................................... 4
Matlab development environment..................................................................................................... 4
Case sensitivity and variable/script/function naming ........................................................................ 5
The “diary” .......................................................................................................................................... 5
The command history and command window ................................................................................... 5
Getting help ........................................................................................................................................ 6
Simple variables in Matlab and some special characters/words ............................................................ 7
Simple variables .................................................................................................................................. 7
Memory usage ................................................................................................................................ 9
“Operational” and “relational” characters, words/variable/constant names in Matlab ................. 10
Other special characters in Matlab ................................................................................................... 11
Single inverted commas ................................................................................................................ 11
Percentage signs ........................................................................................................................... 11
Commas and semicolons .............................................................................................................. 11
Ellipses........................................................................................................................................... 12
Colons............................................................................................................................................ 13
Round brackets ............................................................................................................................. 14
Array variables ...................................................................................................................................... 15
Scalars, vectors and matrices............................................................................................................ 15
Array declaration and initialisation ................................................................................................... 15
Array data access, array indices ........................................................................................................ 16
Efficiency of array usage and memory pre-allocation ...................................................................... 20
Three dimensions and above ............................................................................................................ 20
Scalars, vectors and matrices............................................................................................................ 20
Mathematical operators and usage with arrays ............................................................................... 21
Finding the size of arrays .................................................................................................................. 22
Vectors, sizes and indexing ............................................................................................................... 23
Exercise ............................................................................................................................................. 24
Scripts, functions, debugging and variable scope ................................................................................. 24
Scripts................................................................................................................................................ 24
Functions ........................................................................................................................................... 25
Debugging ......................................................................................................................................... 27
Variable scope ................................................................................................................................... 29
Global variables............................................................................................................................. 30
Variables in scripts ........................................................................................................................ 31
Code looping and branching ................................................................................................................. 31
Code looping: for loops .................................................................................................................. 31
Code branching: if statements ....................................................................................................... 33
Code looping: while loops.............................................................................................................. 35
Error checking and testing .................................................................................................................... 37
Testing for efficiency ............................................................................................................................. 37
Figures and plotting data ...................................................................................................................... 38
Saving data to files ................................................................................................................................ 41
Loading data from files ......................................................................................................................... 41
Strings and interacting with users ........................................................................................................ 41
Prerequisites
It is very much recommended that you have a basic knowledge of another programming language,
e.g. the introductory course on C programming that you should have completed.
An understanding of the strengths and weaknesses of more than one programming language can
bring a greater understanding of how programming languages work in general. Knowledge of several
languages can save much time if the “best” language for the job is chosen from the outset, based on
the project constraints (language functionality, limited processing power, limited memory,
availability of language on platform, etc.).
If you are unfamiliar with C programming, some reading on this language is recommended to allow
comparison with Matlab as a programming language (and because it can be used together with
Matlab – see below). Background reading of “learning” (“how-to” rather than “reference”) type
books would help greatly (e.g. 1,2). Also, general books on programming itself (e.g. 3) would help.
These are available in various quantities in the libraries. Various online sources of material are also
available, but nothing beats a well-established, reviewed and edited book (for a well-established
language like C).
There are books on Matlab (e.g. 4,5), and it is very easy to find a lot of good quality code and tutorials
online. Much can also be learned by checking the help and tutorial features built in to Matlab (see
the Help in Matlab section below).
Course description
This course intends to bring you up to speed with Matlab so that you can use it in the various units
that you take within your MSc. The intention is to talk through usage of Matlab, some commonly
used commands programming structures, and some techniques for creating scripts, functions and
whole programs, plus ways to save and output results so that they can be used elsewhere.
Description of Matlab
Matlab (officially: the rather shouty name of “MATLAB®”) is a programming language and
development environment. Many people come to Matlab thinking that the “Mat” part stands for
“mathematics”, and that it is an environment that is used for doing symbolic maths. While Matlab
does have a toolbox 6 for doing symbolic maths, this was not its initial or main purpose – Matlab
stands for “Matrix Laboratory” and it was initially developed to make matrix calculations and
manipulations simpler to carry out.
Apart from easy matrix manipulations, Matlab allows functions and data to be quickly plotted and
visualised, and provides tools that allow investigations of data to be carried out more quickly than in
many other environments. Matlab also provides tools for creation of user interfaces (UIs, both textbased and graphical) and Matlab code can be interfaced with code written in other languages, e.g. C,
C++, Java, and Fortran (by calling MEX-files, pre-compiled code in DLLs (dynamic-link libraries), or
using other similar techniques.
1
Kernighan, B.W., Ritchie, D.M., The C Programming Language (multiple editions)
Kelley, A., Pohl, I., A book on C :programming in C (multiple editions)
3
B.W. Kernighan, R. Pike, The Practice of Programming
4
B. Hahn, D. Valentine, Essential MATLAB for Engineers and Scientists
5
D.M. Etter, Introduction to Matlab
6
Toolbox: a kind of “add-on” library of tools, which you usually need to pay extra for (to get a licence to run it)
2
Matlab is considered to be a fourth-generation programming language (compare to third generation
languages such as C, Pascal, FORTRAN, and COBOL) and is a high-level programming language
compared to these languages. This means that much of the work of writing programs is hidden away
and programs can be written using far fewer commands and lines of code than in lower-level
languages. This makes Matlab an ideal tool for quickly analysing data, finding solutions to problems
and doing quick “what if” investigation.
Matlab does not require code to be compiled before running (it is an “interpreted” language), as C
and other languages do, and this can speed up development, but may cause the final solution to run
slower. The interpreted nature means that the code can be debugged and additional commands
executed as the code is being run, which can change the course of the program and the end result,
without the need to recompile and re-run the code.
A downside of Matlab is its expense, but if using it as a student or for personal use, licences can be
far less expensive than commercial licences. Additional toolboxes (described later) come with
additional licence requirements, and additional expense. This, and the commercial nature of Matlab
has driven development of open source products like GNU Octave and Scilab, which share some
similar features and language, and so may allow side-by-side development with Matlab, and
relatively easy portability between the products at a lower cost. These come with the downsides of
open source software (e.g. often slow support and product development), but also the upsides (e.g.
inexpensive products that are less likely to be scrapped by a company or fail if the company does).
General tips in using Matlab
Matlab development environment
The main Matlab development environment looks (initially) like this (may differ with version, and
usually does not have this licence warning message!):
The window sections can be moved around to other places in the main window, “unpinned” from
the window into separate, floating windows, etc.
In this default view, though, the current folder ad its (file/folder) contents is on the left, the
command window is in the middle and the workspace and command history is on the right. These
last two show details of the variables within the current “scope” discussed later and a list of recent
commands, respectively (if any). The command window, especially will be used next and other
aspects will be shown later.
Case sensitivity and variable/script/function naming
It is very important to note that Matlab is (generally) case-sensitive, so trying to run the function
cos() , for instance, will not work if you type Cos() or CoS(). It also means that it could be
possible to have multiple very similarly named functions or variables (the same apart from
capitalisation) and so call or use the wrong one.
Variable, script and function names cannot contain spaces or start with a number, though
underscores are OK if you wish to use that form of naming (e.g. Function_name or variable_name,
rather than camel case FunctionName or variableName, or some other format). This therefore (also)
applies to script and function file names – you will not be able to run a script of function if it has a
space in its file name or begins with a number.
The “diary”
You can turn on the “diary” in Matlab by using the diary command. This records everything that is
typed into the workspace, where you will be working to start with, and so you can keep a record of
everything typed in. This will allow you to look back through, and re-run commands, if you would like
to review your learnings.
First, navigate Matlab to the directory where you would like to save files for your this introduction (a
memory stick or a backed-up remote folder on a server that will not be cleared at the end of your
session), using the current folder window, or by typing the path, between single quotes, into the
command window after the cd (change directory) command then pressing [Enter], e.g.:
>> cd 'F:\Introduction to Matlab'
The command cd can also be used to ask Matlab what the current directory is (by typing it on its
own and pressing [Enter]), or using the pwd command (“show (print) working directory”). To move
up a directory from the current one, use cd .. (with a space between the “cd” and the two dots).
After finding your preferred folder, type into the command window:
diary 'MyWorkRecord'
(followed by [Enter], as before) where MyWorkRecord is the name of the file that you want to save
the commands into. Do provide a file extension if you want to open the file in another application at
any other time, as Matlab may not give it one by default.
To stop the diary, use the command diary off. This seems to be done when you close Matlab, but
it’s better to be safe and close the file to make sure it is properly saved and your work is safe and
recorded.
The command history and command window
As you type commands they will appear in the command window. This holds a decent-sized, but not
infinite, list of recent commands, and you can double click on a command to run it immediately, as if
you had typed it into the command window.
You can also run one, or a set of contiguous commands by clicking the first (or last) command you
want to run, holding down [Shift] and then selecting the last (or first) command you want to run in
the list,. Once highlighted, drag these commands across to the command window, then press the
[Enter] key to run the list of commands.
You can select a set of non-contiguous commands by holding down [Ctrl], clicking the commands,
dragging to the command window and then pressing [Enter].
Previous commands can also be run by making sure the cursor is in the command window (flashing
caret – press [Ctrl][0] to get there from any window within Matlab), and pressing the up
arrow/cursor key. If a small amount of text has already been typed in the command window (e.g.
“dia”, for the beginning of the diary command that was typed in), this search of previous
commands will be limited to commands that started (in this case) with the letters “dia”.
Getting help
Please note that you can get help in Matlab at any time by typing (into the command window):
help XXXX
where XXXX is a function name, and pressing the [Enter] key.
This gives a brief description (it prints out the comments just under the function declaration, as
you’ll see later). For instance, if you type help cos, you get:
>> help cos
cos
Cosine of argument in radians.
cos(X) is the cosine of the elements of X.
See also acos, cosd.
Overloaded methods:
codistributed/cos
gpuArray/cos
Reference page in Help browser
doc cos
(Older versions also relay information with the function name capitalised, which is not very useful in
a case-sensitive programming environment)
The underlined blue parts are internal hyperlinks to help on other related functions, and the last one
(with doc in it) will open a help browser pop-up window that gives more help (including images, etc.,
not just simple text).
You can get directly to the more detailed information on variable/function XXXX by typing:
>> doc XXXX
This kind of help only works if you already know the function name, of course, and just want a
reminder. If you are less sure, you can use the lookfor function, e.g.:
lookfor int8
This will (slowly if it’s being used for the first time) look through all of the help and return links to
help topics that contain the word.
Pressing [F1] also brings up a general help browser, or help on something specific if it’s highlighted
(in the command window or the code editor, described later). You can also get help from the “Help”
menu, as ever. There are some general sections that might be worth browsing and there are also
some tutorials available within Matlab itself.
Functions can also be found using the fx “Browse for functions” icon/button just to the left of the
current cursor position in the command window, and they can be searched through in the small popup window using by typing into the search box there.
If you still can’t find help on something, it may not exist in Matlab or the help may just be having an
unhelpful day – try using Google to find what you want instead. There is a very large repository of
code hosted at “MATLAB Central”, and lots of code supplied by others, so someone may have
already done something similar to what you want. Please be careful to check the code for safety,
though and avoid copyright/plagiarism issues, especially during your course.
Simple variables in Matlab and some special characters/words
Simple variables
Matlab is a weakly-typed language and variables can be assigned without first declaring their type
(unless they are to be used for symbolic maths). For example, if x = 21 is typed into the command
window and [Enter] pressed, the following is shown:
>> x = 21
x =
21
The double arrows and space on the first line above (“>> ”) simply show that the command window
is ready to receive a command (i.e. Matlab is not doing something else).
Here, the variable x has been created (declared) and assigned a value in one command. No initial
declaration of the variable is required in C, this would have to be written as something like:
long x;
x = 21;
Other data types (i.e. integers, real numbers, characters, etc.) might be chosen for the declaration,
depending on what “21” meant and what other values it might take, such as:
short x;
unsigned short x;
etc., or even:
float x;
double x;
etc., if the variable is to be used for real numbers.
The declaration and assignment would also have to be surrounded by some kind of function
definition to contain the statement so it could be compiled and there could be no additional
feedback (without additional statements) that x had been given the correct value.
Matlab variables can contain other data types, and their data type can be changed at any time. For
instance, if, having assigned 21 to x above, you then type x = 'Hello world', you would see the
following:
>> x = 'Hello world'
x =
Hello world
Here x‘s data type has been transformed into a string (array) of characters long enough to hold the
characters in the string “Hello world” (11 items, including the space) and the characters have been
added to the array.
Note how Matlab aligns character arrays to the left, but indents values somewhat. This helps you to
see the nature of the variable’s contents if it is not immediately obvious (e.g. a results of 1234 may
be a value or a string of characters).
Transforming from one data type at run time could not be done in C, and an error or something
strange would likely happen if you tried this. If the variable was already assigned as a character type,
changing the number of elements in the array in C would require advance preparation and would
likely stray into more complex programming territories, including use of functions like malloc,
realloc, calloc and/or free for assigning memory before the space can be used to store new
data. This is all handled for you in Matlab.
Matlab variables can also contain additional information about values, such as when handling
complex numbers. If you type z = sqrt(-1) into the command window (where sqrt is the square
root function), you will see:
>> z = sqrt(-1)
z =
0.0000 + 1.0000i
Here the variable z contains both a real and an imaginary part of the resulting variable. You could
instead use the variable i, which is the square root of -1 and add real numbers to get real and
imaginary parts:
>> z = 6.70 + 5.54i
z =
6.7000 + 5.5400i
Variables can also have an array of elements assigned to them at any time (arrays are described
more fully later), for instance if you typed y = [1 2 3] then x = 9 * y then you would see:
>> y = 1 : 3
y =
1
2
3
>> x = 9 * y
x =
9
18
27
Here y is created as an array containing three values, 1, 2 and 3. The previous contents of x are then
discarded and it’s set to be an array of the same size as y, with each of the values in x equal to the
values at the equivalent positions in y, but multiplied by 9.
This shows that variables can be changed by a direct assignment (of constant values) or by
computation in a statement like that above. Here each element of y is multiplied by 9 and the
resulting three-element array is assigned to x.
Variables can also be changed dynamically by the output of a function, so if you now entered x =
sin(0.5), you would see:
>> x = sin(0.5)
x =
0.4794
The contents of x would here revert back to an individual value equal to the sine of 0.5 radians.
For the Sine of the same value in degrees, use the sind function. Alternatively you could convert the
value before using a formula within the function brackets, e.g.:
>> x = sin(0.5 / pi() * 180)
or in one statement, with nested functions (a function call within a function call), using a function
like radtodeg:
>> x = sin(radtodeg(0.5))
The radtodeg function may be part of a toolbox that is not available, but in this case it would be
easy to recreate one, and this would enable easier code reuse and likely cause fewer syntax errors
than frequent use of expressions like 0.5 / pi() * 180 throughout a piece of code. Creation of
functions is described later.
You can see already that it is very quick to open Matlab, try something out and get a result,
compared to a using lower-level language like C.
Memory usage
A downside of this easy variable allocation is that Matlab defaults to using double data types unless
told otherwise. Since doubles use more memory than a lot of other data types, this can lead to
large memory usage when dealing with large data sets (which is often something Matlab is used for).
This can be shown using the whos function, and may also be seen in the workspace window (if it’s
open). If you first type clear into the command window, then this will clear all variables from the
current workspace, releasing them from the system’s memory (it can also be used more specifically
to just clear certain variables, etc.). Then type in some declarations/assignments like those carried
out above, as below (x = 90 [Enter] y = 1.654 [Enter] z = int8(3) [Enter] whos):
>> x = 90
x =
90
>> y = 1.654
y =
1.6540
>> z = int8(3)
z =
3
>> whos
Name
Size
Bytes
Class
x
1x1
8
double
y
1x1
8
double
z
1x1
1
int8
Attributes
You should end up with three variables displayed, the first two being doubles and the last being an
int8 data type.
If the “90” assigned to x would always be an integer within a program, and one that would only ever
be between the values -128 and 127, it could have been defined as an int8, but Matlab doesn’t
know this, so it will play safe and use a double, which uses more memory (8 bytes compared to 1 –
see above) but can contain a much wider variety of values. This was explicitly done in the
declaration/assignment of z by using the int8 function, which converts variables of other data
types to signed (i.e can be negative or positive) 8-bit integer data types (as there are 28 = 256
possible values from -128 to 127).
The 1x1 part shows that these are individual (scalar) values (essentially a 1 by 1 array of values, as
everything in Matlab is an array – this is discussed next).
Each data type requires a certain amount of memory and has lower and upper limits to the values
that can be assigned. These are listed under “Strategies for Efficient Use of Memory” in the help,
together with some useful strategies for efficient memory usage, if this turns out to be an issue.
“Operational” and “relational” characters, words/variable/constant names in Matlab
These characters and words in Matlab are similar to many other languages, including C. As with C,
there is a distinction between the operational equals/equation operator, “=”, which makes
something equal to something and the relational equals/equation operator, “==”, which asks
whether something is equal to something else. As such, the relational equals is like a function with a
return value of 0 for false (“no, they are not equal”) and 1 for true (“yes, they are equal”).
The arithmetic operators (+, -, *, / and ^), and other similar operators are similar to C and many
other languages when used with scalar values. When used with arrays (matrices), their behaviour
can differ, and this is discussed in the section on array variables.
The relational operators for “is less than”, “is greater than”, “is less than or equal to” and “is greater
than or equal to” are <, >, <= and >=, as with many other languages. The operator for not equal to is
“~=” (some other languages use “!=”, “<>” or other systems).
Again, these relational operators return a true or false value, which means that they can be used for
branching logic in your program (where decisions to do one thing or another are made).
Some reserved words in Matlab include i and j, to represent the square root of -1, NaN, to
represent a result that is not calculable (“not a number”), eps, which gives the accuracy of floating
point numbers (no number is infinitely accurate when calculated by computer, and rounding errors
can occur), Inf, which represents a value that was calculated as being infinite, and pi, which
contains the value of pi.
Caution should be used, as Matlab’s flexibility with use of variables means that it does not stop you
overwriting i, say, with something else (another number or array of values), and until you call the
clear function or restart Matlab, the variable will not contain its original value and meaning. Even
something like the function clear could be overwritten so that it becomes a variable (e.g. if you
typed -- but please don’t! -- clear = 56 , Matlab would refer to that variable, rather than the
function name (seemingly) until you restarted Matlab, as you could no longer use clear to delete
from the memory clear.
The section "How MATLAB Recognizes Command Syntax" in the Matlab documentation describes
Matlab’s interpretation of what you ask it to do.
Other special characters in Matlab
Some special characters that Matlab uses include single inverted commas, percentage signs,
commas, semicolons, ellipses, colons and round brackets.
Single inverted commas
These are used to enter strings into variables, or to send strings to functions.
A single inverted comma after a matrix (after the variable that represents a matrix, e.g. mat1'),
transposes that matrix.
Percentage signs
Percentage signs (%) are used at the front of anything that is a comment. Use comments to explain
parts of the program that may not be easy to follow (though if you can make your code easy to
follow by using helpful variable and function names, that can help more than not doing so, and
having to rely on explanation through comments).
Comments will not be executed as code, and they can take up an entire line or be put at the end of a
line of code.
It is also worth mentioning that the use of white space (especially blank lines) can greatly aid the
readability of code and this, together with comments, can help to divide sections from each other
and make the resulting program easier to read and understand. These do not slow the program
down in any way as they are disregarded by the interpreter.
Commas and semicolons
Commas and semicolons are used in arrays to separate columns and rows, respectively. For instance,
typing k = [1, 2, 3; 4, 5, 6] into the command window would give:
>> k = [1, 2, 3; 4, 5, 6]
k =
1
2
3
4
5
6
Here, the commas specify that 1, 2 and 3 (and 4, 5 and 6) should be put into separate, consecutive
columns, while the 1, 2 and 3 should go in the first row, and then 4, 5 and 6 should go in the second.
Commas do not have to be use in this way – spaces can be used on their own instead, as with the
previous declaration/assignment of y. Semicolons must be used, though, if assigning arrays in this
manner. Arrays will be discussed more later on.
Commas can also be used to separate multiple statements on one line, thought this can make
programs less clear and may be harder to debug, so unless they are extremely short statements it is
probably best avoided. An example might be:
>> l = 6, m = 25, n = 2
l =
6
m =
25
n =
2
This will execute each of the three statements in turn, as shown. Commas are also used to separate
function arguments (variables sent to functions), e.g. rand(2, 3), a function call that will return an
array of random numbers between 0 and 1 with two rows and three columns (six values in all).
Up until now, Matlab has echoed back to you the result of all of the assignments and calculations
that you have typed into the command window. The same would be the case for all statements (that
return a result). If a semicolon is used at the end of a statement, however, this tells Matlab to
supress the result. So if you typed a = 345; at this point, Matlab would declare a and set it to be
an individual value of 345, but return nothing as confirmation that this had happened:
>> a = 345;
Gives no result back. You can check the value in a, by just typing a and pressing return (without
typing a semicolon):
>> a
a =
345
Its value will also be shown in the workspace window, if it is open, and whos or (more specifically)
whos a would say something about the size and type of a.
Other related, and useful commands, include which, which indicates whether an identifier is a
variable, a built-in Matlab function (and where it is located on your system), user-defined function,
or something else, and what, which lists files in the current directory.
While it might be good to have the results of operations shown to you in the command window as
you go along, once a piece of code grows to encompass many operations, the constant printing of
results to the command window significantly slows the progress of the code. In this case you might
want to terminate with a semicolon most, or all, commands that report results to the command
window.
Statements in Matlab are therefore terminated with a commas, semicolons, or just a carriage return
(new line), as with the first commands that you typed into the command window.
Ellipses
Since a new line can indicate a new statement, but long lines (over 80 characters long) can make
code hard to read (especially if the user needs to scroll sideways), an ellipsis (three full stops /
periods, “...”, not the single character that represents a ellipsis, “…”) can be used to continue code
from one line to the next without separating the statement into two, thus:
>> l = [1 2 3 4 5 6 7 8 9; ...
9 8 7 6 5 4 3 2 1]
You will note on typing the ellipsis then pressing the carriage return, that Matlab does not create any
output, as it is waiting for you to finish the statement (complete the second row of the array, in this
case).
Please note, any additional spaces in Matlab are not considered by the code interpreter. So these
the statement b = [2
56] will be interpreted in the same way as b = [ 2 56 ] or b=[2,56].
Note also that (as above) spaces are not needed around the equals/equation operator (=), the
arithmetic operators (+, -, *, / and ^), and other similar operators that have characters distinct from
the alphanumeric characters (A-Z, a-z, 0-9 and underscore) that are allowed in variable and function
names. Spaces here are personal choice, and may be added for legibility, but Matlab does not insist
on it.
Colons
Colons are used to create vectors and sequential values, for accessing subsets of values in arrays and
in creation of for loops. Examples of these are:
>> d = 1 : 0.5 : 3
>> l(:, 2:3) = -1
and
>> for indx = 0 : 1 : 4
h = indx * 2
end
The first command sets a new variable, d, to be the values the result from incrementing from 1
upwards with an increment of 0.5 until the value 3 is reached (or exceeded). It therefore returns the
result:
d =
1.0000
1.5000
2.0000
2.5000
3.0000
If the last value were exceeded during the incrementing, it would not be included, so
>> d = 1 : 0.5 : 3.1
would give the same result for d.
The second command indicates that within the array l, the elements that match the criteria of being
in any row (the colon on its own, “:” is shorthand for “1:end”, which means from the first row to
the last row, i.e. all rows, as discussed in the section on finding the size of arrays) and between the
second and third column (inclusive) should be set to a value of -1. It should therefore return:
l =
1
-1
-1
4
5
6
7
8
9
9
-1
-1
6
5
4
3
2
1
as the 2 and 3 in the first row, and the 8 and 7 in the second are set to 1.
Arrays will be discussed in more detail below.
The third command (or set of three commands, representing the setting up of the for loop, a
command that is repeatedly carried out as long as the for loop continues, and the closing statement
of the for loop) will result in a set of outputs from:
h =
0
to
h =
8
as each time through the for loop, the value of indx is incremented from a starting value of 0 by a
value of 1 (the middle “1” in the for statement), until it reaches (or exceeds) the value 4. Within the
loop, h is set to twice the value of indx, and since there is no terminating semicolon, the result is of
the calculation is echoed to the command window.
The colon used to create the array in d is closely related to the syntax used in the for loop, and like
the assignment of d using the colon notation, if the first line of the first for loop read for indx =
0 : 1 : 4.1, the loop would not be run for indx with a value of 4.1.
The array in d could be built up using a for loop, with a similar structure to the statement that
assigned the array to d:
>> for indx = 1 : 1 : 5
d(indx) = 1 + ((indx – 1) * 0.5)
end
The first assignment of d is clearly quicker to type, and due to the way that Matlab functions, will
also be quicker to execute.
Here, the increment of the for loop has a value of 1. Since this is the default in Matlab, the middle
part can be ignore and for loop line could read for indx = 1 : 5.
You will also note that when typing this into the command window that Matlab will not execute any
part of the for loop until it is complete (the closing end has been typed).
For loops will be discussed more later on.
Round brackets
These are used in a similar way to most other programming languages, that is to say for calling
functions, for accessing particular elements of an array, of for forcing precedence where it might
otherwise not occur.
An example of the last usage would be (56 + 87) * 6, which would add the two numbers before
multiplying. This is against the normal order of operator precedence in Matlab, which is:
1. Brackets (())
2. Transpose (.'), power (.^), complex conjugate transpose ('), matrix power (^)
3. Unary plus (+), unary minus (-), logical negation (~)
4. Multiplication (.*), right division (./), left division (.\), matrix multiplication (*), matrix right
division (/), matrix left division (\)
5. Addition (+), subtraction (-)
6. Colon operator (:)
7. Less than (<), less than or equal to (<=), greater than (>), greater than or equal to (>=), equal to
(==), not equal to (~=)
8. Element-wise AND (&)
9. Element-wise OR (|)
10. Short-circuit AND (&&)
11. Short-circuit OR (||)
Array variables
Scalars, vectors and matrices
As mentioned above, all variables in Matlab are arrays. 1 x 1 arrays are referred to as scalars, 1 x n
arrays (a single row of values) or n x 1 arrays as vectors (a single column of values), and n x m arrays
are known as matrices or arrays (2D arrays). Multiple dimension variables (3D or more) are usually
known as arrays.
Array declaration and initialisation
Arrays can be declared in a number of ways. Some have been seen already, where an array can be
declared and initialised with a set of constant values in one statement. These could equally well have
been pre-defined variables (like p and q, below), so an array could be created as follows:
>> p = 1; q = 2; r = [p q; q p]
r =
1
2
2
1
Here p and q are declared, with the semicolons suppressing the echoing of the results of these
declarations, and then they are used to create a 2 x 2 array, r, with the values within p and q being
used to set the values within r.
This is a one-off operation – no link is implied between the value of p, q and r in the future and they
are not bound in any way; these are just a set of sequential commands. So if p and/or q change
value at a later point, and the command r = [p q; q p] is not run again, there would be no
change in the array r as a result of p and/or q changing.
Arrays can also be created and filled with zeros or with ones using the zeros or ones commands.
This may seem an odd thing to do at first, but it can have its benefits, as described below.
If you want an array to be filled to a known size with the same, known value in each position, say, a 4
(rows) x 3 (columns) array with 7 in each position of the array, then you could use the ones function,
multiplying the result by 7, to get something like:
>> arrayOfVals = ones(4, 3) * 7
arrayOfVals =
7
7
7
7
7
7
7
7
7
7
7
7
Reasons for using the zeros function include that given in the section on efficiency of array usage,
below.
Array data access, array indices
Accessing data in an array requires use of indices of the array row and column (for a 2D array – more
indices are needed for an array with more dimensions). Say an array were created by typing:
>> s = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
s =
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
To access the position where the value is 10, you would need to type s(3, 2) – the third row and
second column, to access the position where the value is 8, you would need to type s(2, 4) – the
second row and fourth column.
To change the value at the third row and second column from 10 to 300, you could use:
>>s(3, 2) = 300;
If the semicolon were omitted, it would echo back the values of the entire array, showing the array
after the change, and thus showing what had changed:
s =
1
2
3
4
5
6
7
8
9
300
11
12
13
14
15
16
To add the values in the second and third column in the second row together and then put them into
the top, right position, the command would be:
>>s(1, 4) = s(2, 2) + s(2, 3)
s =
1
2
3
13
5
6
7
8
9
300
11
12
13
14
15
16
To access a sub-set of the rows, the colon can be used, as described previously, thus:
>>s(1:3, 2:4)
Since the result is given nowhere to “go” (there was no variable associated with the result of what is
essentially a function call), it is allocated to Matlab’s ans variable, which holds the “most recent
answer”:
ans =
2
3
13
6
7
8
300
11
12
This shows the array between rows 1 and 3 and columns 2 and 4 (inclusive).
The ans variable is generally not used directly (as with other variables) – as soon as another
calculation is done, the new “most recent answer” will replace what was in the variable, so the next
calculation using ans would be different to the previous one (e.g. type 1[Enter], then ans+1[Enter]
several times in a row – each time the value of ans becomes one more than previously).
If the command were s1 = s(1:3, 2:4), then the result would be put in a new variable, s1 , and
it can therefore be further manipulated as a sub-set of the values of s. As discussed above, however,
the values are not linked to s, and s can be changed without s1 being updated.
A colon on its own (as mentioned previously) would give all rows (if in the first index position) or all
columns (if in the second).
Variables can be used in place of these values (they do not have to be constant, but must be
integers, not numbers with fractional parts, and must be within the bounds of the array), so this
would also work:
>> s2 = s(p:q, 2:3);
This can be a useful way to index through an array, if needed – you can increment (or otherwise step
through) the value in a variable to move through the various positions within an array, using the
index variable to indicate a specific point in the array, and so use or change a value at that point.
Since the content of variables can be replaced at any time, arrays can change size, and Matlab allows
for an array to expand to a size to include a new value inserted into it, for instance, if you were to
type:
>> s(5, 6) = 31
Matlab would expand the array to allow the new value, entering at row 5, column 6, with any other
unspecified values in the array being set to zero, so the result would be:
s =
1
2
3
4
0
0
5
6
7
8
0
0
9
10
11
12
0
0
13
14
15
16
0
0
0
0
0
0
0
31
While writing to a non-existent array location expands the array to include the position and add the
value in, trying to read from non-existent location will generate an error.
Arrays have to have the same number of rows and columns (and the same through the other
dimensions) throughout – i.e. they cannot be “ragged arrays” (as can be possible in some other
programming languages), where there are a different number of elements, e.g. if the number of
columns varied throughout the rows, so this assignment would not be possible:
>> s = [1 2; 5 6 7 8 9; 10 11 12; 13 14 15 16]
The error given would say:
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
This is as the command above is essentially taking four arrays (a 1 x 2, 1 x 5, 1 x 3 and a 1 x 4 array)
and trying to concatenate them (join them together) in the “vertical” direction (along the first
dimension, which is the row direction).
The first command for assigning s:
>> s = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
is actually shorthand for:
>> vertcat([1 2 3 4], [5 6 7 8], [9 10 11 12], [13 14 15 16])
where four arrays, each of one row and four columns are concatenated together in the vertical
direction, or even more generally:
>> cat(1, [1 2 3 4], [5 6 7 8], [9 10 11 12], [13 14 15 16])
where the same four arrays are concatenated together along the first dimension, which , as
mentioned above, is the direction “down the rows).
The second assignment of s does not work, therefore, as the arrays have o all be the same “width”
to be concatenated in the “height” direction. To illustrate this further, this would work, and result in
the same array as s was (originally, before elements of it were changed):
>> s3 = cat(1, [1 2 3 4], [5 6 7 8]);
>> s4 = [9 10 11 12];
>> s5 = [13 14 15 16];
>> s5 = cat(1, s3, s4, s5)
s5 =
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Here, a 2 x 4 array is made, then two more 1 x 4 arrays, and these are all the same width, so they can
be concatenated together in the first dimension. The shorthand for this would be (using nested
square “array assignment” brackets):
>> s6 = [[[1 2 3 4]; [5 6 7 8]]; [9 10 11 12]; [13 14 15 16];]
Or the easiest way would just be as with the original assignment of s. So there are many ways to
assemble arrays in Matlab.
A section of array could be replaced with another section of an array, e.g.:
>> s5(3:4, 3:4) = [-1 -2; -2 -1]
This would replace the bottom 2 x 2 part of the s5 array, leaving:
s5 =
1
2
3
4
5
6
7
8
9
10
-1
-2
13
14
-2
-1
If a sub-matrix is added to the array as above, but at indices that don’t exist, the array will expand to
fit in the extra values, as shown earlier for adding in individual values (with zeros again filling any
unspecified regions – e.g. try the command s6(4:5, 8:9) = [-1 -2; -2 -1]).
Parts of arrays can also be deleted, though those parts this would have to be entire rows or columns,
or sets of rows or columns, or a ragged array would result. This can be done by assigning them to be
empty, using the open and close square brackets with nothing between them (“[]”), e.g.:
>> s5(1, :) = []
s5 =
5
6
7
8
9
10
-1
-2
13
14
-2
-1
This deletes all of the columns (“:”) in the first row (“1”).
This open-close bracket arrangement can also be used to declare an array that starts empty, or to
make an existing array (completely) empty. For instance the following set of commands shows the
declaration and initialisation of a variable as an empty array, checking it using whos filling it with
some values, checking it again, then making it empty once more and one final check.
>> s7 = [], whos s7, s7 = [44 55 66; 77 88 99], whos s7, s7 = [], whos s7
s7 =
[]
Name
Size
s7
0x0
Bytes
0
Class
Attributes
double
s7 =
44
55
66
77
88
99
Name
Size
s7
2x3
Bytes
48
Class
Attributes
double
s7 =
[]
Name
Size
Bytes
Class
Attributes
s7
0x0
0
double
Note the size of 0 x 0 indicates an empty array, and there is a function to check this state, too,
named isempty. To test this, try:
>> isempty(s7)
ans =
1
This “true” return value indicates that the variable is indeed empty.
Efficiency of array usage and memory pre-allocation
It might seem a good idea, and more memory-efficient, to use Matlab’s dynamic variable-changing
abilities to expand an array only once a new piece of data is obtained and it is ready to be placed in
the array, expanding the arrays as the program progresses, but this turns out to be an inefficient way
of doing things.
As mentioned before, to change the size of arrays in a lower level programming language would
require calls to functions to allocate memory for additional data within the array and may require
moving blocks of memory around, making copies of data and then deleting it from the sections of
memory available. If this were happening every time new data was created or received from an
analysis or data logger, it would require constant shuffling of large amounts of data around the
memory spaces. Although Matlab makes this easy for you, it still has to do these operations “under
the hood” and as just as inefficient at these operations as these lower level languages, as that is
what the program is ultimately written in.
In Matlab, it generally more efficient to pre-allocate memory for an array, to be at least as large as
the amount of data that you expect to put in it, and then fill it in the appropriate places as you
progress through your process. This may require more memory initially, but it is more efficient.
This is usually what the zeros function is used for, therefore: fill an array with zeros then add pieces
of data in as they become available, in the next “empty space” (the next zero, row of zeros, etc.).
Newer versions of Matlab have (in the code window, which you will see later) orange indicators
down the right hand side of the (code) window (which you will see later) that show where code may
not written as efficiently as possible,. This is one of the inefficient coding practices that is
highlighted. Another is the lack of termination of lines that would echo results to the command
window, as described earlier – both slow the code down significantly.
Three dimensions and above
For more information, see “Building a Preallocated Array”, and the other parts within the “Resizing
and Reshaping Matrices” section in the help browser (the “full” help, rather than the brief one given
in the command window).
Scalars, vectors and matrices
Matlab can handle 3D arrays and arrays with many additional dimensions, though these can be
much harder to visualise and display on a screen, and if displayed are shown in “layers” in the
command window, where the rows and columns in the first “depth” dimension is shown first, then
the second, and so on.
This can be illustrated by making a 3D (2 x 3 x 4) array, as follows:
>> layer1 = [1 2 3; 4 5 6];
>> threeDimArr = [];
>> threeDimArr(:, :, 1) = layer1 * 1;
>> threeDimArr(:, :, 2) = layer1 * 2;
>> threeDimArr(:, :, 3) = layer1 * 3;
>> threeDimArr(:, :, 4) = layer1 * 4
To explain this, a 2D (2 x 3) array was created, a variable threeDimArr declared (and initialised as
empty – note 3DArr would not be a valid Matlab variable name) before adding in the 2D arrays in
“layers”, each layer being 1, 2, 3, and finally 4 times the values in the first. Since the last line
contained no semicolon, the fully formed array should be shown in the command window, one
“layer” at a time.
The array was initially specified as being empty, in case such a variable already existed, as if it did,
there might have been a concatenation error if it was a different size to the 2D matrices that were
being added in slice, by slice.
A way to do this in one statement is to use the cat function along the third dimension, as below:
>> cat(3, layer1 * 1, layer1 * 2, layer1 * 3, layer1 * 4)
Check that the function call above gives the same result (by, for instance, assigning it to a different
variable, then subtracting one from the other, which should result in an array of the same size, full of
zeros).
Try the size function on this array, too, to see how the size of 3D arrays is reported.
Mathematical operators and usage with arrays
When + and - are used with two scalar values, they are simply added together or subtracted as
normal.
When adding or subtracting a scalar to/from a matrix, the scalar is added to or subtracted from (or
the matrix is subtracted from the scalar) in an element-wise manner, i.e. each element in the array
has a value added or subtracted, or is subtracted from that value.
When used between two matrices, an element-wise addition or subtraction will occur, but only if the
two matrices have the same dimensions.
When *, / and ^ are used between two scalars, their behaviour is as normal.
When * and / are used between a matrix and a scalar, the matrix is multiplied or divided by the
scalar.
When multiplying two matrices, the number of columns in the first matrix should match the number
of rows in the second (this is a proper matrix multiplication, rather than an element-wise one).
With division, the two matrices need to have the same number of columns, so a scalar could only
precede a matrix if it was a column matrix (again, this is a proper matrix division, rather than an
element-wise one).
Matrices can be raised to the power of a scalar (e.g. c^2 is the same as c*c), but the matrix must be
square (due to the multiplication rule given above).
In order to get element-wise multiplication, division or powers of matrices, a dot should be put
before the *, / and ^ operators, making them .*, ./ and .^.
Unless specifically carrying out matrix operations (e.g. data and coordinate transformations), it is
more common to want to multiply, divide or get the power of a set of numbers in an array in an
element-wise fashion, but it is very easy to forget to use the dot-version of these operators.
There is also a backslash divide operation, or “left matrix divide”. This is used like A \ B, where the
result is the matrix division of A into B, which is roughly the same as INV(A) * B , i.e. B (matrix)
multiplied by the inverse of A. This is often used for finding the solution of a set of simultaneous
equations.
It is worth trying these operators out in as many ways as you can find, using combinations of scalars,
vectors and matrices to make sure that you understand the actions that they allow.
Finding the size of arrays
Since arrays can change size, it’s important, before doing something with an array, to know how
large it is.
The word end can be useful in this situation, as it signifies the maximum index (i.e. the maximum
row, column, etc. number) of an array, so it can even be used without explicitly knowing the size of
an array. In its use to find the maximum index of an array (in a particular dimension) it can be used
on its own, or like a variable, e.g. s5(1:end-1, :), which would indicate all columns of s5 and
rows from 1 to the second-to-last (i.e. rows 1:(4–1) or 1:3, as end is equal to 4 for this dimension
of this array).
These uses of the colon (to mean “all”, or 1:end) were briefly mentioned earlier.
The size of an array can also be found using the size function, e.g.:
>> s5ArrSize = size(s5)
s5ArrSize =
3
4
Here, s5 is passed to the size function and the result is returned into a new variable named
s5ArrSize. Since the array is a 2D array, two values are returned, i.e. the variable that is returned
and passed into s5ArrSize is an array with two elements. These elements specify the size of the
array in the same order as Matlab dimensions are specified in, i.e. number of rows, then number of
columns, then number of “depth” layers, etc.
To obtain just the size of one dimension, and return an individual value, a second argument, that of
the dimension required, is passed to the size function, so the results of testing these two
individually would be:
>> s5NumRows = size(s5, 1), s5NumCols = size(s5, 2)
s5NumRows =
3
s5NumCols =
4
where this time the number of rows in s5 has ended up in the variable s5NumRows and the number
of columns in s5 has ended up in the variable s5NumCols. You should see how these variables could
then be used as (upper) limits so that the rows and columns might be iterated through, from the
lower index limit to the upper index limit, filling in values, for instance.
Note that the lower limit of arrays in Matlab is (generally) a value of one, rather than a value of zero,
as in some other languages (i.e. some languages have arrays whose indices run from 0 to n-1,
whereas Matlab’s run from 1 to n, where n is the number of elements in the array).
Other useful functions related to manipulating arrays and their sizes include reshape, rot90,
fliplr, flipud, flip and transpose (the last doing the same as the single quote operator
mentioned above). Take a look at the help entries for these to understand what each of them does,
and try them out on a 2D matrix to show their effects. You might like to also look at the “Resizing
and Reshaping Matrices” help topic for more information.
Vectors, sizes and indexing
Vectors (1 x n “row arrays” or n x 1 “column arrays”) are a special case compared to arrays with
more than one dimension. These arrays are often created using the notation similar to that seen in
the command d = 1 : 0.5 : 3, above, where a regular sequence of values is required. This
would create a single row of values, whereas the command dDash = (1 : 0.5 : 3)' would
transpose the vector seen in d before assigning it to dDash, giving a column vector.
Since vectors only have one dimension, indexing is simpler, as only one value needs to be given,
regardless of whether it is a row or column vector. So all of these values would be the same: d(1,
4), dDash(4, 1), d(4), and dDash(4). Check this for yourself and make sure that you
understand this indexing.
It is also possible to index through, say, a 2D array using only one index, and the order that the value
will be returned in, with an increasing value of the index is the value in the first row, first column, to
the last row, first column, then the first row, second column, to the last row, second column, and so
on until the row of the last column. Try this by using the following commands:
>> s8 = [1 2 3; 4 5 6; 7 8 9]; disp(s8); disp(s8(1:prod(size(s8))));
The first command makes a 3 x 3 matrix, s8, the second displays it using disp and the third displays
the values in sequence, with the index of s8 going through each of the values from 1 to 9. Here the 9
is arrived at by using the size function to return a two element vector containing the array size (3
rows and 3 columns), multiplying these together using the built-in Matlab function prod, which
multiplies together all of the elements in an array (along one dimension only – like several functions
in Matlab it works along the “first non-singleton dimension” unless specified otherwise – see the
help on this function for more information).
A function that works in a similar way is sum (see the help for more details on that function, and
note how it works on both row and column vectors and on 2D or higher dimension matrices).
Matlab code can be very compact – this kind of output might take several lines to achieve the same
result in another language. There is a danger that increasing levels of terseness will remove
meaning, however, and so the code may be “better” (easier to understand and use, and/or maintain
at a later date, even if not as compact, or maybe even as efficient) if nesting many functions in this
way is avoided in actual programs that you write. At the very least, they may require more
commenting.
The size of vectors can also be found using the length function, which returns only one value,
unlike the size function, which returns two values even in the array only has one dimension (one of
the size values is simply “1” – the first if it’s a row matrix or the second if it’s a column matrix).
This also works on arrays with more than one dimensions, but returns only the largest dimension
(equivalent to doing max(size(X)), where the max function returns the maximum element in any
array). It is recommended for matrices with two dimensions or more that a more specific approach is
taken, using size, especially if array dimensions might change throughout the code.
Exercise
The mathematical term dot product (“∙”) refers to an operation carried out, usually on vectors, that
results in a single value, where for example:
[1, 3, -5]∙[4, -2, -1] = (1 * 4) + (3 * -2) + (-5 * -1) = 4 - 6 + 5 = 3
Using what has been explained above, find two different ways to calculate the dot product of two
row vectors, the first containing the values 1, 2 and -3 and the second containing the values 3, 6 and
7. The answer should be -6. Try and find the shortest way possible (shortest command) and try and
make your solution as general as possible (i.e. it should still work if the number of elements in both
vectors changes).
Scripts, functions, debugging and variable scope
Scripts
A script is as simple as being a text file (with the file extension “.m”) with a set of commands in it.
Since these files can be saved they are a good way to write and maintain code. Any of the commands
that you’ve been typing into the command window can be placed in a script.
You’ll now move to using the editor, and so the diary that you set going may be less useful, as it
saves only the commands typed into (or otherwise executed) in the command window. You could
stop it if you like, or leave it running to catch any additional commands that are entered.
To open the editor, you could make a new M-file – there are many ways, including suing the “New
Script” menu/button, the “New” drop-down list menu/button (then selecting “Script”), press [Ctrl]N
to open a new script, or press [Ctrl][Shift]0 (zero) to shift to the editor (from the command window,
which you can get back to using [Ctrl]0).
Once you have a new script open, the first thing you should do, to avoid losing work, is to save the
new script as something sensible. Remember not to use numbers at the start or spaces. Remember –
to avoid losing work: save early, save often! Matlab does auto-save, but it’s best not to reply on
these files. Also, while there are multiple levels of undo, it might be best to regularly save versions of
the file as you go along (e.g. FileName001.m, FileName002.m, etc.), so if you go down a long branch
of changing code that doesn’t work, you can get back to a previous version that worked. Earlier
version can always be discarded once you are happy with a final chunk of code.
You might want to undock (right click the top of the code editor sub-window and press “Undock”), if
it starts in a docked format, and have it float above the other windows (within Matlab’s main
window), so that switching between these is a (maybe) easier [Alt][Tab] rather than the other
shortcuts/mouse clicks and to give more screen “real estate” to the other windows within the main
one.
To make a script that would carry out the previous actions you set in place to create vectors and find
the dot product of them move back to the command window, copy the code from the command
window or the command history window and paste it into the editor.
All “>>” and extra spaces (at the front of lines of code) that you might copy across from the
command window should be deleted, leaving just the individual commands, preferably one per line
on the editor. Please also keep all lines to no more than 80 characters long by using ellipses.
Once you have the set of commands in the code editor and you have saved the file, the commands
can be run by clicking the “Run” button, or pressing [F5]. If this works, you should see the script
name appear in the command window, as this is the other way to run the script (type its name into
the command window and press [Enter]). The code will be run and any commands that you have left
“open” (with no semi-colon afterwards) will echo assignments, etc. back to the command window.
When writing a standalone piece of code (i.e. there are no proceeding scripts or functions called),
you may want to put the following three commands at the top (or a subset of them if not all are
needed):
close all;
clear;
clc;
These commands close any figure windows that might be open (described later), clear all (nonglobal) variables in the current workspace/scope and clear the command window, leaving you with a
clear view of the results of the script’s actions.
Anything that comes up in terms of new windows or output in the command window will be as a
result of this script and not any previous scripts or commands directly typed into the command
window, so no confusion can occur.
So, you now have a piece of code that you can run any time you like, and this piece of code can even
be run by another script, or directly from the command window, just by typing its name on its own
line.
If that script is saved in another folder, though, a full or partial path to the file will be required. A
partial path is only required for folders below the current one (e.g. run('Test
folder\TestScript001.m')), but a full one is required if the folder is on a different folder
“branch” (e.g. run('C:\Matlab files\Test folder\TestScript001.m')). Since this sends
the string representing the file name and path to the run statement in quotes (as a string, or
character array), spaces are allowed in any of the folder names (the file name should still be spacefree, though).
The code is rather limited, though; it would only be able to do the dot product of two particular
variables unless it was changed each time. It would be better to be able to do the dot product of any
two (row) vectors. For that, you could use a function. These are described next.
Functions
As another example of a set of operations that might be put into a function, we could look at the
Fibonacci sequence. This starts with two ones and all subsequent values in the sequence are the sum
of the two previous values.
Say you wanted to find the total of a particular Fibonacci sequence, maybe the numbers 1, 1, 2, 3, 5,
8, 13, 21, 34, 55, 89 and 144, you could make a script named “TotalTheseVals.m” containing the
code:
%Show the total of a particular Fibonacci sequence.
valArr = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144];
totalOfSeq = sum(valArr)
Running this would give an output, but it would only work for one particular sequence, not any
sequence, and so would need to be manually changed to get any other total value.
You can make a function that does the totalling part, but for any array of values that is sent to it. This
is a rather trivial thing to make into a function, but this is just the first example, and it will be
improved later. To start with, you should make a new function.
Newer version of Matlab make it easy to make a new function by using the “New” drop-down list
menu/button (then selecting “Script”). This creates the outline of a function:
function [ output_args ] = Untitled3( input_args )
%UNTITLED3 Summary of this function goes here
%
Detailed explanation goes here
end
The outline shows you what’s needed, with the initial and final (opening and closing) keywords of
function and end, an initial function name of UntitledXXXX and the position that input and
output arguments should go, between round and square brackets, respectively.
It also shows the initial comment, which Matlab uses to relay help to the user. To illustrate this, you
should (select then over)type (or delete then type) TotalValues as the function name, and then
saved the file with the name “TotalValues.m”. Matlab has been checked to see if it already has a
function or variable of this name and it does not – this is worth doing to make sure there is no
confusion later on. The function name (at the top of the code in the file) should match the file name
– this is how Matlab finds the functions it is asked to run.
Once this is done, go to the command window and type:
>> help TotalValues
UNTITLED2 Summary of this function goes here
Detailed explanation goes here
You will see that the comment at the top of the function (just underneath the line with function
on it) was returned by the help function.
Typically, the first part (without any indenting after the % comment character) is where you would
write a brief summary of the function, then you would write a more detailed description underneath
that, with some indenting, to separate the two sections (visually) from each other. This a
recommended format – you could write anything there, but it’s best to stick to standards.
Other things can be included in the text returned by help, too. For example, if you look at help for
the function cos (type help cos), and then look at the function for cos (type edit cos and it will
open in the code editor), you’ll see how the comment and the text returned by help compare. You
can only see the “top” (description) of this function, as it is a built-in function, which is pre-compiled
and can’t be edited, but it still requires a help entry, which this provides.
Note that there is a part that says “See also” in the comments. This is a sign to Matlab to make the
next two functions mentioned into click-able hyperlinks. You could do the same in your function if
there were related functions – just add the names of functions that Matlab can find in the current
directory, or in the other paths that it looks at (type path into the command window and look at
help path to find out more about these paths).
Note also that the help function stops relaying these comments to the command window once it
reaches a blank space (or other non-comment line) that breaks up the block of contiguous comment
lines at the top of the function.
So, next you should change the UNTITLEDXXX in the comment at the top of the function to be the
same as the actual function name and write something informative below, following the format
shown.
Also the input_args and output_args variables should be changed to variable names that are
more appropriate for this function. In this case, change input_args and output_args to
valueArray and totalOfValueArray, respectively, as describes what they are (what will be
passed into and returned from the function).
This is a simple function (but can demonstrate some useful things), so just put this line of code inside
it, after the comment at the top:
totalOfValueArray = sum(valueArray);
Once saved, the function can be run. Try this first from within the command window, by typing:
>> TotalValues
You will see an error message indicating that at least one input argument was not passed to the
function that it needed to complete its job (“Not enough input arguments”). It also shows the
line on which the error occurred (“Error using TotalValues (line XXXX)”).
To investigate this more fully, you can make the code go into debug mode.
Debugging
Go to the line of code in the code editor with the sum function on it. Either press [F12] or left-click
on the small line just to the right of the line number (itself to the left of the line of code). Only
executable lines of code have these small lines next to them – you’ll see none of these on lines with
comments on, or blank lines, for instance. This will toggle a red dot on/off, indicating a breakpoint.
Alternatively, to put a breakpoint on the first executable line in this file, type dbstop in
TotalValues in the command window.
Code in Matlab runs linearly through from the top to the bottom (unless cycled back up to a
previous line using a for loop or similar). If code execution is about to execute a line that has a
breakpoint on it, it will stop and wait until some action is carried out by the user. The point where
the code has “reached” in its execution is shown with a small green arrow pointing to the right.
Run the code again by typing TotalValues in the command window (or using the up arrow key
until that command is reached), then return to the code window and you should see the code has
paused on the line with the breakpoint (it is now in debug mode), with the green arrow pointing at
the line that will be executed next.
Normally, if you hover your mouse over a variable in debug mode, Matlab will show you what it
contains (or an overview if it’s a big array). Hovering over the variables on the line of code
(valueArray and totalOfValueArray) shown nothing, though, indicating they do not exist, at
least within the current “scope” (discussed below).
This can also be seen by briefly going to the command window again and typing whos. While in
debug mode, commands can be executed and they will be run just as if they were a line of code
being run, or as commands normally run when not in debug mode. You can see that nothing is
returned, so no variables are present within the current “scope”.
You will also notice that the usual “>> ” prompt in the command window is replaced with “K>> ”,
to show that Matlab is in debug mode.
It is natural for totalOfValueArray not to exist, as it has not been declared or set to anything
previously, and this line would do that, except that valueArray does not exist either, so if the code
continued, it would try to take do sum on a non-existent valueArray and pass the result into
totalOfValueArray. To show this, first a brief discussion of the debug tools.
Some of the icons/buttons at the top of the code window change to allow debugging functions to be
used.
These functions include (not in this order on the screen):
 “Step In”, which runs through the code one line at a time and “steps into” any called functions or
scripts it comes across, with the debugging moving to the first executable line in the file for that
called function or script. Hovering the mouse over this button shows the shortcut to be [F11].
 “Step”, which does the same, but steps over any called functions or scripts it comes across,
continuing in the current file (but not stepping down into “sub-files”), with the shortcut [F10].
 “Step Out”, which carries on until the execution has left the current file and returned to the “file”
(or other script/function/place) that called it, with the shortcut [Shift][F11].
 “Continue”, which allows the code execution to go off again at normal speed and no longer in
debug mode, at least until it might encounter the another breakpoint, or the end of the program,
with the shortcut [F5].
 “Run to Cursor” – place the cursor on a line and press this button to get the code to run until It
reaches the line with the cursor on, (no shortcut key). This is equivalent to setting another
breakpoint on the line with the cursor on and pressing [F5], then removing the breakpoint again.
So to make the line execute, press any of the shortcut keys above to get the next line to execute. The
code will stop regardless of which is used and the same error will be shown in the command
window.
So you can see that if you pass nothing into the function (as an input argument) then nothing will
end up in the variable valueArray and so no calculation can be done using it.
To remedy this, type the following in the command window:
>> valArr = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144];
>> TotalValues(valArr)
This makes an array, valArr, and passes that array into the function TotalValues as the first (and
in this case, only) input argument.
If the breakpoint is still present on the (only) executable line of code within, the execution will stop
there again; hover over the valueArray variable again to see what it contains. This can be done at
either position of valueArray in the function (in the brackets at the top, where it comes in as an
argument) or on the line that’s about to be executed.
Now it has a value, it can be used, so press Step ([F10]) to step through that line of code and execute
it. The green arrow should move on to the end keyword/function (so that is the next thing that will
be executed), and if you hover your mouse over the totalOfValueArray variable, you’ll see that
it’s been assigned as a result of the sum function call.
Note that this function could be called from a script, or another function, as well as it could be called
from the command window.
Also note that while this function only had one input argument and one output argument, it is
possible to have multiple input and/or output arguments, and these can all be of different types.
Functions can also have also can have optional arguments, so a function can be called in a variety of
ways, and different functionalities can be set up within the function, depending on the number
and/or type of arguments that are set to the function. See the function nargin in the (full) help (i.e.
doc nargin) for more information and examples.
Variable scope
There are some more things to take away from this.
Firstly, that the variable valArr was passed into the function in the first (and only) input argument
position, and in the process, a copy of this was made in memory and it was assigned to the variable
valueArray – this was deliberately made a different name to illustrate this. If the input argument
within the function file was named AAbbEESADJWE it wouldn’t make any difference – the first
argument in the list in the place that calls a function gets copied into the first argument that is listed
in the function itself (at the top of the file).
To illustrate that what is in the function (in valueArray) is a copy of valArr and not the same
thing (the same point of the machine’s working memory), before exiting the function (now that
totalOfValueArray has been assigned), empty the contents of valueArray using the command
valueArray = [];, then press press [F10] twice more to execute the end function and then leave
the function completely (or press [F5] just once to continue until this function is exited on and exit).
If valueArray and valArr were the same variable, in the same piece of memory, then valArr
would also have been emptied, but typing its name in the command window (after the function’s
exited) or typing whos shows that it’s still the same as it was before the function was called.
Also you will see that totalOfValueArray has been deleted from the list of variables – this also
only exists for the duration (or scope of the function) and is deleted once its value has been passed
back to the workspace. In this case it’s passed into ans.
If the calling statement in the command window were terminated with a semicolon, the return value
would still be passed into ans, but this would not be reported in the command window. If the call
was instead resVal = TotalValues(valArr) then the “result” of this function (the output
argument) would be returned into the variable resVal. A semicolon wold suppress reporting of
this, too.
One more thing to note is that within the scope of the function, only variable that have been passed
into the function and those created within the function can be “seen” by the function.
To show this, again run the code (using TotalValues(valArr)) to the point where the line of
code is about to be executed, then return to the command window and type whos. You will see that
the only thing that exists in the current scope is valueArray. Press press [F10] once to step on and
calculate totalOfValueArray and you will see, on returning to the command window and typing
whos again that there are just the two variables now that were passed into, and created inside, the
function. Step on or continue until the command function is complete and you from another can call
to typing whos that the scope of the workspace has again been resumed, with the variables that
were there before still there (the value in ans will have been updated) and that were present when
within the scope of the function have been deleted from memory.
This is true of all layers of functions – if the function you were just inside called another function,
that function would not have access to the workspace’s variables or those within the function that
called it.
Global variables
The exception to this rule is that of global variables, but Matlab is slightly odd in its use of global
variables.
They can be declared somewhere (say, the workspace, or a script or function that calls another
function). They can then be shared with the sub-functions that are called form there, but only if they
are also declare the same variable name as global within the sub-function. In most programming
languages, variables declared as global just tend to be available to all procedures (functions, etc.)
regardless of location or need for declaration within the sharing procedure (especially if declared at
the declaring a variable at the “top level” of the program). Some languages also have more than one
level of “global-ness” to their variables.
Alternatively a global variable could be created within a sub-function and later shared with another
function “higher up” the function “call stack” once declared in there (but this might be less likely).
In any case, the variable needs to be declared, for instance by using a statement like:
global testVar;
in two separate functions (or other places, like a function and the workspace, with generally nonshared scope) and this then allows those places to get access to the same piece(s) of data, at the
same point in memory.
These can be large arrays or individual values, like any other variables.
An advantage of global variables include the ability to share large arrays between functions without
making copies of them in memory, allowing multiple functions to access the data in the same
array(s). This can save excessive duplication of data, which, when working with large data sets, can
make Matlab run out of memory.
While this can happen when sending large blocks of data to functions in Matlab, it is generally more
of a problem in older implementations of Matlab. In newer versions it appears that if the array
passed to a function is not changed, it represents the same piece of memory (i.e. it is passed “by
reference” as can be done explicitly in C), but if the array is changed in any way, a copy of that array
is made and the change that was made is applied to the copy of the array. At this point, memory
usage could jump up significantly if large data sets are being passed to a function. This is a relatively
complex issue and so help should be sought in the case of memory issues.
Also, some of the comments just before this “Global variables” section may be somewhat simplistic
in their discussion of variables passed to functions, but it is still the case that a variable passed to a
function that is then changed does not change the original variable that was passed, but a local copy.
Another advantage of global variables is that a large number of variables might be more easily
shared between a script, function or the workspace, and a called function, without requiring a long
list of input and output arguments in the called function (or the place it is called from).
Note also that breakpoints also appear to be held in global memory and so cleared when the clear
all command is issued (but not the clear command without the all).
Variables in scripts
One more comment to make on variables and their scope is that variables in a script are shared with
whatever place called them (script, function or the workspace), as a script just represents a
collection of commands that are run as if they were run within the location that called the script.
Code looping and branching
Code looping: for loops
To illustrate an example of a code looping construct, you shall use a for loop in the following code.
Since the summing part in the function that was just created was the only thing that happened
within the function, it was a rather trivial a use of a function. Making a function that created a
Fibonacci sequence up to a certain value or up to a certain total value (when all values are summed)
would be more useful as it would replace several lines of code in the original script with one function
call.
Recall that the previous function, TotalValues, only totalled values sent to it, and was really
therefore just duplicating the work of the sum function. Also recall that the Fibonacci sequence was
just created manually using a set of values (valArr = [1, 1, 2, 3, 5, 8, 13, 21, 34,
55, 89, 144];). A function can be made to automate this so it does not have to be manually
created.
Make another function as you did before and call it FibonacciSequenceTotalToTerms, in the
function name and the file name. Add an input argument, numTerms and an output argument,
totalOfSeq. Add in a useful comment for help to report on, then add in the code for the function.
The file might end up looking like this:
function [totalOfSeq] = FibonacciSequenceTotalToTerms(numTerms)
%Total of a Fibonacci sequence up to a certain number of terms.
%
%
This function creates a Fibonacci sequence up to the number of terms
%
given in numTerms, then totals all of the terms and returns the total.
%Pre-allocate the memory for this array.
fibSeq = zeros(numTerms, 1);
%Allocate the first two values, which are always 1 and 1.
fibSeq(1) = 1;
fibSeq(2) = 2;
%Continue from term three until the end of the array, filling the array
%with values that are the sum of the previous two values, as per the
%Fibonacci sequence.
for indx = 3 : numTerms
fibSeq(indx) = fibSeq(indx-1) + fibSeq(indx-2);
end
%Total the terms in the sequence and return that total value.
totalOfSeq = sum(fibSeq);
%End of the function (if this is in its own file, with no other functions
%or anything else below the last line of code before this, then the end
%statement is optional.
end
Now the usefulness of the function is clearer – by running this function, and sending only one value
to it, into numTerms, the code can create a Fibonacci sequence up to this number of terms total the
terms and return the result.
Even better, once this function is created and checked, you don’t even have to know, or care (as long
as you trust the person who wrote it!) what goes on inside – the values are created, added and
destroyed again once the function is complete, leaving only the result that you wanted – the total.
Run the code by entering, say:
>> FibonacciSequenceTotalToTerms(14)
And you should get a return value of 1595.
Use dbstop in FibonacciSequenceTotalToTerms or manually put a breakpoint on the first
executable line then run the code again using the same command, requesting the total to 14 terms.
As you can see (hover over these with the mouse), the variable numTerms has accepted the inout
argument (the constant value 14), and doing whos will show that to be the only variable in the
current scope.
Stepping on a line (e.g. [F10]) initialises fibSeq to be a vector that has numTerms rows and 1
column (it could have been the other way around, as you will remember from the section on
indexing vectors, as is done in the for loop next).
Two more steps sets the first two values in the vector.
In the for loop (one of a set of looping constructs), the variable indx is set to take each of the
values in turn between 3 and has numTerms (14, in this case).
Step into the loop, past the “opening” line of the for loop to the single line within, then before
stepping any further, check the value of indx. It should be 3, and it will be used as an index of the
vector fibSeq, assigning to fibSeq(3) (the first time through the loop) the value that the sum of
fibSeq(3-1) and fibSeq(3-2), i.e. fibSeq(2) and fibSeq(2), the two values before the
“current” value.
Take one more step and you will see that this value has been assigned.
Since Matlab can’t display too many values in the “datatip” (yellow box that pops up when variables
are hovered over), if you were using a big data set you could check the values at these positions by
selecting one of them in the code, say, fibSeq(indx) and then pressing [F9], which will execute
whatever is selected in the command window (a shortcut to selecting, copying, going to the
command window, pasting and pressing [Enter]. In this case it should report a value if 3. You could
do the same for fibSeq(indx-1) and fibSeq(indx-2), or any other existing variable (in scope).
Stepping a few more times shows that the for loop is repeated, and each time execution point is
stepped past the end statement, the value of indx is incremented, and so the insertion point for
the new value in the vector fibSeq is moved on one (from index 3, to 4, to 5, etc.) and the indices
of the two values being added together to make the value entered in that position are also indexed
on, so the value entered is always the sum of the two previous values.
Stepping on some more shows that the two lines of code that are executed repeatedly are the line
inside the loop and the end statement – the opening line is only run once, so if a breakpoint were
put on that, the code would only stop once.
If the for loop were to be done many times, and it had been sufficiently examined, another
breakpoint could be placed on the next statement after the for loop and [F5] pressed, or the cursor
could be placed there and the “Run to Cursor” button pressed.
Stepping on, the last statement is executed, summing all of the elements in the vector fibSeq and
the function is then exited, assigning the answer to ans.
If whos is run again, it can be seen that the variables that were used inside the function have been
deleted.
Code branching: if statements
An alternative function that allows the user to find out how many terms it would take to reach, or
exceed, a certain total.
Since, if an arbitrary total were given, it would not be clear how many terms in a Fibonacci series
would be require to reach (or exceed) that total, this code would not be able to give an immediate
answer. It would instead have to increase the number of terms in the Fibonacci series, checking the
total each time the number of terms was increased, until the total met or exceeded input argument
value, then return from the function with the number of terms that met the input criterion.
This would require a code branching construct like an if statement, resulting in a function like:
function [numTerms] = FibonacciSequenceTermsToTotal(totalOfSeq)
%Number of terms required to reach, or exceed a given total of a Fibonacci
%sequence.
%
%
This function takes as an input the total of a Fibonacci sequence up to
%
the number of terms and iterates through a sequence until it is found
%
how many terms are require to reach, or exceed, that total. The number
%
of terms is returned in numTerms.
%Pre-allocate the memory for this array. It was previously found (using the
%function) that the maximum number of terms in these sequences could be
%1473 before the sequence reached an "infinite" number (beyond a double
%type's upper limit of approx. 1.7977e+308).
numTerms = 1473;
fibSeq = zeros(numTerms, 1);
%Allocate the first two values, which are always 1 and 1.
fibSeq(1) = 1;
fibSeq(2) = 2;
%Continue from term three until the end of the array, filling the array
%with values that are the sum of the previous two values, as per the
%Fibonacci sequence.
for indx = 3 : numTerms
fibSeq(indx) = fibSeq(indx-1) + fibSeq(indx-2);
%If the required total has been equalled or exceeded, set the number of
%terms to the current value of indx, then exit the function.
if sum(fibSeq) >= totalOfSeq
numTerms = indx;
return; %Exits the function immediately.
end
end
end
Here the function name has been changed, the input and output arguments swapped to represent
the opposite functionality, and an if statement has been added to the for loop.
Since the approach here is slightly different, the number of terms (and thus the initial size of the
vector holding the Fibonacci sequence) is unknown. A maximum possible size is set, therefore. The
maximum size was found using the previous function, increasing the number of terms until the
resulting total returned Inf, showing that the total of the sequence was an "infinite" number
(beyond a double type's upper limit of approx. 1.7977e+308 – not infinite, but very large).
So, numTerms can be initially set to this maximum size (1473), this can be used to size the array and
if a total is found that exceeds the total required, the number of terms taken to reach that point can
be entered into numTerms and the function can be exited using the return statement (directly,
without any more loops being carried out).
If a small total is entered, the process can be followed through step by step using debug mode, as
before, to show the sequence of commands carried out.
If returned Inf is entered, the loop will run to the maximum number of 1473, the value in
numTerms remaining unchanged as the if statement is never true, so the code within is not run.
If the for loop only needed to be exited within the if statement – maybe some more code needed
to be done to finish things off before exiting the function – then a break statement could be used in
place of the return statement. This would move to the next line of code after the for loop that the
code was currently in. This also works for other looping constructs like the while loop discussed
next.
Code looping: while loops
A while loop is an alternate looping construct that repeatedly executes statements while a condition
is true, so it contains both a looping element and a testing element, unlike a for loop, which loops
through statements for a fixed number of times, incrementing a variable each loop.
The same function can be rewritten to use a while loop:
function [numTerms] = FibonacciSequenceTermsToTotal_W(totalOfSeq)
%Number of terms required to reach, or exceed a given total of a Fibonacci
%sequence.
%
%
This function takes as an input the total of a Fibonacci sequence up to
%
the number of terms and iterates through a sequence until it is found
%
how many terms are require to reach, or exceed, that total. The number
%
of terms is returned in numTerms.
%
%
This function is like FibonacciSequenceTermsToTotal, but uses a while
%
loop rather than a for loop.
%Pre-allocate the memory for this array. It was previously found (using the
%function) that the maximum number of terms in these sequences could be
%1473 before the sequence reached an "infinite" number (beyond a double
%type's upper limit of approx. 1.7977e+308).
numTerms = 1473;
fibSeq = zeros(numTerms, 1);
%Allocate the first two values, which are always 1 and 1.
fibSeq(1) = 1;
fibSeq(2) = 2;
%Continue from term three until the end of the array, filling the array
%with values that are the sum of the previous two values, as per the
%Fibonacci sequence.
indx = 2;
while sum(fibSeq) < totalOfSeq
%Increment indx (this was previously inherent in the for loop).
indx = indx + 1;
%Continue finding the total until it is equal to or greater than the
%required total.
fibSeq(indx) = fibSeq(indx-1) + fibSeq(indx-2);
end
%Set numTerms to the current value of indx - this is the number of terms
%needed to meet or exceed the required total.
numTerms = indx;
end
Here, the while loop can test for whether to continue or not, so the if statement that was inside
the for loop can be used instead as the conditional statement that the while loop requires.
The while loop, on the other hand, does not inherently increment anything each time it completes a
loop, so for this problem, indx is used like a counter that it incremented by 1 each time through the
loop in a separate statement (1 is added to its current value and that value is reinserted back into
indx).
While this kind of loop can be used for this problem, the logic is somewhat reversed compared to
the way it was written with the for loop.
Since the while loop executes the code within while something is true, but the previous if
statement exits the code only if something is false, the logic of the conditional statement is reversed
from sum(fibSeq) >= totalOfSeq to sum(fibSeq) < totalOfSeq.
The starting value of indx also needs to be 2, rather than 3 in the for loop, as it need to be
incremented before the total is calculated, or the check would exit on the total being met or
exceeded with a value one greater than required.
This is because in the original version the execution goes:
add new value > check total > exit if total met or exceeded (at if line) > increment indx and loop
(at end line)
But if the while loop version went:
add new value > increment indx > check total (at while line) and exit if total met or exceeded
then the value in indx would be one more than the actual number of terms required to get to the
total, as it was incremented after the total was calculated. But if it is incremented before:
increment indx > add new value > check total (at while line) and exit if total met or exceeded
then the value in indx needs to start one lower than it wold otherwise be, as it is incremented
before it’s used in the line that adds a new value into index 3 (on the first iteration). Either this or
the first version would have to be used, but 1 subtracted off the final value of indx before setting
the return value and exiting the function.
If this was not thought through carefully, and tested with a variety of values, this error might have
been missed. This is a very common error, where the result is “off-by-one” and is at least slightly
related to the “fencepost” error (described here: http://en.wikipedia.org/wiki/Off-by-one_error) –
another indexing-type error that is easy to miss.
It can be seen, therefore, that the functionality of the for and while looping constructs differs, and
that one may be better suited to any particular problem than the other – here it’s seen that
workarounds/adjustments have to be made that leave the final code looking less obvious than it
might otherwise be, which would require at least some additional commenting.
Error checking and testing
It can be seen from the issues with the code above that testing you code is essential, and it should
be done with a wide range of inputs wherever possible – it’s safer to assume your code is broken
until you’ve proved beyond reasonable doubt that it isn’t.
To do show how to do some basic testing, Try running the (simpler) function with some other inputs
to see how it reacts (the first, FibonacciSequenceTotalToTerms, function). Try to push the code
to the limits of the values that might be entered – large values, small values, negative values,
integers, non-integers, strings of characters, etc. to see if/where it fails.
You will note that only one value can be sent to this function – if you tried to input, say [15 16 17]
to get a variety of outputs, it causes the function to fail. It could be altered of course, to allow a
vector (or array of any size) to be sent to it if it were changed to allow this. You might like to think of
how this could be achieved, and how the results would be sent back (preferably in an array of the
same size, with totals in).
The function is also limited to only being able to run on input values that are positive integers, of
value 3 and above, and there is likely to also be an upper limit, due to the somewhat exponential
nature of the output vs. the input.
It is important for code that is to be used by others, or reused in many places, that it be robust, and
so it is always worth keeping in mind the ways that code might fail and what can be done to alleviate
these failures.
Testing your code with a wide variety of inputs also allows you to know how best to run that code,
what its failure conditions might be and so allow you to limit what is passed to it, or better still, give
it some inherent way of “gracefully failing” if a certain input, command, etc. were known ahead of
time to cause failure. The code could then avoid running certain commands with fail-prone inputs,
perhaps, by branching off to give an error message or flag (an indicatory value in an “error code”type variable) or simply returning something like a zero value in the return variable.
Testing for efficiency
It is wise to check code for efficiency, too. This is probably not as necessary when there are few
operations or small amounts of data involved in a program, but time savings can often be made if an
eye is kept on using efficient coding practices.
For instance, the FibonacciSequenceTotalToTerms function uses memory pre-allocation to
speed up the values being entered into the vector (as mentioned previously), rather than expanding
the vector as the code proceeded.
The duration of four calls to this function were recorded using tic and toc, a pair of statements
that when called in that sequence reports the time elapsed between the calls, creating a simple
method for timing chunks of code, thus:
>> tic, FibonacciSequenceTotalToTerms(1400), toc
ans =
7.2473e+292
Elapsed time is 0.000910 seconds.
Here, the total of a large number of terms is found and it is seen that it took 0.9100 ms. The average
of four of these (timings do vary somewhat, depending on what the PC is doing) was 0.0011 s.
The pre-allocation line was commented out (so it did not run) by placing a percentage sign at the
front of the line ([Ctrl][R] automates this on the line(s) that are selected and [Ctrl][T] “un-does”
comments one at a time). The file was saved (otherwise Matlab may run the old, unsaved and
unchanged version) and run again several times, with the last four times giving an average time of
0.0028 s. While these are both very quick indeed, the pre-allocation method can be seen to be
faster, and the differences would be greatly magnified with large datasets.
Doing the sum of the entire vector (sum(fibSeq)) every iteration , in the if statement in the
second function (FibonacciSequenceTermsToTotal) was also found to be slower than
accumulating a total in a separate variable as the sequence was expanded. Code to implement this,
in FibonacciSequenceTermsToTotal2, requires a bit more explaining, though and may be less
clear, so there may be a trade-off between clarity, brevity and speed.
Figures and plotting data
Some simple data plotting and visualisation will be discussed next. Simulated data is created in the
script CreateSimulatedAcquiredData (in the file “CreateSimulatedAcquiredData.m”).
Open that file in the code editor, and you will see that it is created using commands that should
already be familiar to you.
Time data is created (in variable timeData) that runs from time = 0 s to time = 10 s, with an interval
of 0.001 s. This might represent the time intervals that accompany data that have been acquired
from a data acquisition device or piece of data analysis code, with a sample frequency of 1 kHz.
The data itself is relatively simple and consists of a main sine wave (perhaps from an oscillating piece
of machinery, though it could equally well be the voltage across two wires in a piece of electrical
equipment, etc.). Since this represents real-world data, there is two “layers” of noise added to the
main sine wave, at lower amplitude and higher frequency.
A figure is created to plot the data on. This is always a good idea when handling data as it
immediately allows you to visualise the data and check it seems as you expect. It is far harder to get
an understanding of data just from the values it contains.
You should have a look at the help for the plot command, and other commands used in the script.
There are also some comments in the file, but the help will give more information in all cases. This
shows the basics of plotting data on a 2D plot, and annotating the plot and the figure itself with
various labels.
Also, make sure you step through the code one line at a time and check that you understand what
each line is doing.
Once the plot is present, you could also try the text command, which puts text of your making on
the plot relative to a point (relative to the values on the axes) that you specify (as X-Y coordinates,
on a 2D plot). You could put a label on to say what the peak values, were, for instance, and the line
function could allow you to draw a line from the point to meet the text placed on the plot.
Also make sure you have a go with the buttons on the toolbar that allow you to zoom into and out of
the plot (reset to the original view with a double-click), rotate the plot (makes more sense with 3D
plots) put a data cursor on the plot to show a particular value, and various other tools, all of which
have help available.
There are also several ways in which you can save the plot, including to standard image formats
(some giving better output quality / smaller file size than others) and the opportunity to save as a
“.eps” file. This is a type of vector image, which is infinitely scalable rather than “jaggy” when
zoomed into as with raster graphics, and can result in a file both of much smaller size and much
higher quality (especially for simple line-type images, such as the plot shown.
Please see the Wikipedia entry on vector graphics if you are unfamiliar with them, which can be
found here: http://en.wikipedia.org/wiki/Vector_graphics. Using this kind of image in a report
(especially with the use of editors/PDF compilers like LaTeX, etc.) can result in high quality, yet very
compact output files (especially good quality PDFs). If inserting into MS Word, “.emf” or other
formats might be more appropriate. Experimentation is recommended. Programs like Ghostview can
be used to view EPS files.
Use of vector graphics and editors/PDF compilers like LaTeX can be a somewhat complex subject,
but the end results usually exceed the quality of those produces using “standard” tools such as MS
Word, especially when creating larger thesis-type works.
Figures can also be saved as “.fig” files – Matlab’s own format that saves all of the current settings of
the figure, together with the data within, and allows the figure to be re-opened and edited if
required.
All of these saving options can be reached using Matlab functions, too, so a piece of code can be
written that not only analyses and plots data, but saves it in your preferred format. This can allow
standard output formats to be created, which can take the manual labour out of creating multiple
figures, and help them to maintain a more uniform look between images, as every aspect can be
controlled.
You will notice that when the figure was created, using the figure command, the result was placed
in the variable figNum. This is a “handle” to the figure itself (there are also handles to parts of it, like
the axes within), and allows commands to be used that are directed at the figure. For instance, the
command print(figNum, '-depsc', 'TestImg') will “print” that figure to a colour EPS file
named “TestImg.eps”, or the option '-dpng' instead of '-depsc' will print to a PNG file instead.
There are many more options that allow the setting of resolutions and sizes (especially for for raster
images) and much can be found in the full help for the print command (type doc print).
The 'Name' and 'Data to save to file' parts shows the use of a property name-setting pair,
where the property 'Name', here is set to the string 'Data to save to file'.
Properties of “objects” that you have obtained handles to can be fund using the get command,
which should be used like this: get(figNum). This will produce a list of the properties associated
with that object and the handle to it allows access to these, via the property-setting pair.
So looking at the properties for the figure, whose handle is figNum, you might see that the property
Color is set to [0.8 0.8 0.8], showing the red, green and blue “channels” of the colour that
makes up the background (values going from 0 = none to 1 = full saturation). To set this to a
different colour, you could type:
>> set(figNum, 'Color', [0 0 1])
which would set the background of the figure to blue. Matlab uses RGB (red, green and blue, in that
order) values, usually ranging from 0 to 1 or 0 to 255 to allow colours to be specified. So [1 0 0]
would set things, the background in this case, to red, [0 1 0] would set it to green, [1 0.5 0]
would set it to orange, etc. A few standard colours can also be used, e.g. 'b' for blue. These are
listed in the line colours seen in help plot. Line styles and symbols are also listed.
When the command plot(timeData, testData1, 'r'); was issued, a handle to that series of
data (the line, series of dots, or similar seen on the plot, depending on the line style, etc.) could also
be obtained, e.g. using testData1Hdl = plot(timeData, testData1, 'r');. Again,
information on this series (once it’s been plotted and the handle obtained) can be found using the
handle name and get:
>> get(testData1Hdl)
This would return the current settings for this series and then set used, with the handle name and
an appropriate property-setting pair to change the series style, markers, line colour, etc., or even the
data itself.
Getting handles to the series and changing the data through set(handleName, 'xdata',
xDataValues); is the best way to change data if the data is to be updated regularly, as in an
animation, scrolling through a series of data, or otherwise showing data in a more dynamic manner
(rather than plotting the data only once for a static plot). If the plot were repeatedly updated using
the plot command, rather than via the series’ handles, the plot can become quite flickery. A
smoother animation can be obtained using the handles method. This was especially an issue with
older versions, but may also improve plotting in newer versions.
Other properties that can improve animation are setting the 'DoubleBuffer' property of gcf, the
handle to the figure itself, which can always be used after a figure has created, to 'on' (this allows
an off-screen pixel buffer to be assembled and then printed to the screen once the drawing is
complete, allowing flicker-free rendering, and setting the 'DrawMode' property of gca, the handle
to the figure axes, which can be used after a plot has been made on the figure and so “axes” are
present, to 'fast', which speeds up plotting by ignoring the relationships of the objects in three
dimensions (e.g. sorting depending on view, etc.).
Many other plot types are available as standard, and it is always possible to programmatically
construct your own plots, as it is very easy to create 2D or 3D data at points, and “join the dots” to
create shapes and wireframe type graphics. Patches can also be created, which represent a filled 2D
polygon filled with a colour of your choice, allowing assembly and rendering of 3D surfaces and
shapes (see patch, fill, fill3, etc.). Being able to do all of this programmatically and repeatably
allows many kinds of rich visualisations to be created.
Using the inbuilt functions can give you a useful plot in very few steps, though, and functions like
plot, plot3, surf, mesh, etc. should be investigated to see what they can provide. The full help
generally gives at least one representative example that can be tested out and investigated. The “2D and 3-D Plots” section in the help is very useful and describes many ways of creating and using
these data visualisations, as well as animating them and recording these animations to movies that
can be played outside of Matlab.
Saving data to files
The data is saved in files in a variety of ways in the script SaveSimulatedAcquiredData. These all
have their own advantages and disadvantages. It is worth looking up all of the options for these
methods of saving in the help.
Loading data from files
Depending on the method and file type that the data was saved with and into, the re-loading
procedure will be different.
Mat files can be loaded just using load, but files saved (more manually) to text files and similar will
require other, probably more complex methods of loading the data back into Matlab. See functions
like fopen, how to use its output arguments (including optional ones),
Strings and interacting with users
Strings (of characters) act very much like arrays of values in Matlab, but they are rendered as the
characters according to their ASCII code. It is important to understand how to concatenate these,
convert values to use with strings and assemble them into messages that can be written to files,
displayed in plots, or otherwise relayed to users, if meaningful feedback is to be given. Functions
such as disp, num2str, sprint, msgbox, input, etc. are important here.
Download