This repository has been archived on 2021-05-17. You can view files and clone it, but cannot push or open issues or pull requests.
scientificComputing/programming/lecture/programming.tex

1533 lines
58 KiB
TeX

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Programming in \matlab}
\section{Variables and data types}
\subsection{Variables}
A \enterm{variable} is a pointer to a certain place in the computer's
memory. This pointer is characterized by its name, the variable's
name, and the \enterm{data type} (figure~\ref{variablefig}). In the
computer's memory the value of the variable is stored in binary form
that is as a sequence of zeros and ones (\enterm[Bit]{Bits}). When the
variable is read from the memory, this binary pattern is interpreted
according to the data type. The example shown in
figure~\ref{variablefig} shows that the very same bit pattern is either
interpreted as a 8-bit integer type (numeric value 38) or as a
ampersand (&) character. In \matlab{} data types are of only minor
importance but there are occasions where it becomes important to know
the type of a variable and we will come back to them later on.
\begin{figure}
\centering
\begin{subfigure}{.5\textwidth}
\includegraphics[width=0.8\textwidth]{variable}
\label{variable:a}
\end{subfigure}%
\begin{subfigure}{.5\textwidth}
\includegraphics[width=.8\textwidth]{variableB}
\label{variable:b}
\end{subfigure}
\titlecaption{Variables.}{Variables are point to a memory
address. They further are described by their name and
data type. The variable's value is stored as a pattern of binary
values (0 or 1). When reading the variable this pattern is
interpreted according to the variable's
data type.}\label{variablefig}
\end{figure}
\subsection{Creating variables}
In \matlab{} variables can be created at any time on the command line
or any place in a script or function. Listing~\ref{varListing1} shows
three different possibilities:
\begin{lstlisting}[label=varListing1, caption={Creating variables.}]
>> x = 38
x =
38
>> y = []
y =
[]
>> z = 'A'
z =
A
\end{lstlisting}
Line 1 can be read like: ``create a variable with the name \varcode{x}
and assign the value 38''. The equal sign is the so called
\codeterm{assignment operator}. Line 5 defines a variable \varcode{y}
and assigns an empty value. If not explicitly specified \matlab{}
variables will have the \codeterm{double} (a numeric data type, see
below) data type. In line 9, however, we create a variable \varcode{z}
and assign the character ``A'' to it. Accordingly, \varcode{z} does
not have the numeric \codeterm{double} data type but is of the type
\codeterm{character}.
The actual data type of a variable can be found out with the
\code{class()} function. \code{who} prints a list of all defined
variables and \code{whos} provides detailed information
(listing~\ref{varListing2}).
\begin{lstlisting}[label=varListing2, caption={Requesting information about defined variables and their types.}]
>>class(x)
ans =
double
>> who
Your variables are:
x y z
>> whos
Name Size Bytes Class Attributes
x 1x1 8 double
y 0x0 0 double
z 1x1 2 char
\end{lstlisting}
\begin{important}[Naming conventions]
There are a few rules regarding the variable names. \matlab{} is
case-sensitive, i.e. \code{x} and \code{X} are two different
names. Names must begin with an alphabetic character. German (or
other) umlauts, special characters and spaces are forbidden.
\end{important}
\subsection{Working with variables}
We can certainly work, i.e. do calculations, with variables. \matlab{}
knows all basic \codeterm[Operator!arithmetic]{arithmetic operators}
such as \code[Operator!arithmetic!1add@+]{+},
\code[Operator!arithmetic!2sub@-]{-},
\code[Operator!arithmetic!3mul@*]{*} and
\code[Operator!arithmetic!4div@/]{/}. The power is denoted by the
\code[Operator!arithmetic!5pow@\^{}]{\^{}}. Listing~\ref{varListing3}
show their use.
\pagebreak[4]
\begin{lstlisting}[label=varListing3, caption={Working with variables.}]
>> x = 1;
>> x + 10
ans =
11
>> x % x has not changed!
ans =
1
>> y = 2;
>> x + y
ans =
3
>> z = x + y
z =
3
>> z = z * 5;
>> z
z =
15
>> clear z % deleting a variable
\end{lstlisting}
Note: in lines 2 and 6 the values of the variables have been used
without changing their values. Whenever the value of a variable should
change, the \code[Operator!Assignment!=]{=} operator has to be used
(lines 14 and 18). Line 23, finally shows how to delete a variable.
\subsection{Data types}
As mentioned above, the data type associated with a variable defines how the stored bit pattern is interpreted. The major data types are:
\begin{itemize}
\item \codeterm{integer}: Integer numbers. There are several subtypes
which, for most use-cases, can be ignored when working in \matlab{}.
\item \codeterm{double}: Floating point numbers. In contrast to the
real numbers that are represented with this data type the number of
numeric values that can be represented is limited (countable?).
\item \codeterm{complex}: Complex numbers having a real and imaginary
part.
\item \codeterm{logical}: Boolean values that can be evaluated to
\code{true} or \code{false}.
\item \codeterm{char}: ASCII characters.
\end{itemize}
There is a variety of numeric data types that require different memory
demands and ranges of representable values (table~\ref{dtypestab}).
\begin{table}[t]
\centering
\titlecaption{Numeric data types and their ranges.}{}
\label{dtypestab}
\begin{tabular}{llcl}\hline
Data type & memory demand & range & example \erh \\ \hline
\code{double} & 64 bit & $\approx -10^{308}$ to $\approx 10^{308}
$& Floating point numbers.\erb\\ \code{int} & 64 bit & $-2^{31}$
to $2^{31}-1$ & Integer values. \\ \code{int16} & 16 bit &
$-2^{15}$ to $2^{15}-1$ & Digitizes measurements. \\ \code{uint8}
& 8 bit & $0$ bis $255$ & Digitized intensities of colors in
images. \\ \hline
\end{tabular}
\end{table}
By default \matlab{} uses the \codeterm{double} data type whenever
numerical values have to be stored. Nevertheless there are use-cases
in which different data types are better suited. Box~\ref{daqbox}
exemplifies such a case.
\begin{ibox}[t]{\label{daqbox}Digitizing measurements}
Scenario: The electric activity (e.g. the membrane potential) of a
nerve cell is recorded. The measurements are digitized and stored on
the hard disk of a computer for later analysis. This is done using a
Data Acquisition system (DAQ) that converts the analog measurements
into computer digestible digital format. Typically these systems
have a working range of $\pm 10$\,V. This range is usually resolved
with a precision of 16 bit. This means that the full potential range
is mapped onto $2^{16}$ digital values.\vspace{0.25cm}
\begin{minipage}{0.5\textwidth}
\includegraphics[width=0.9\columnwidth]{data_acquisition}
\end{minipage}
\begin{minipage}{0.5\textwidth}
Mapping of the potential range onto a \code{int16} data type:
\[ y = x \cdot 2^{16}/20\] with $x$ being the measured potential and $y$
the digitized value at a potential range of $\pm10$\,V and a
resolution of 16 bit. Resulting values are integer numbers in the
range $-2^{15}=-32768$ to $2^{15}-1 = 32767$.
The measured potential can be calculated from the digitized value
by inverting the equation:
\[ x = y \cdot 20/2^{16} \]
\end{minipage}\vspace{0.25cm}
In this context it is most efficient to store the measured values as
\code{int16} instead of \code{double} numbers. Storing floating
point numbers requires four times more memory (8 instead of 2
\codeterm{Byte}, 64 instead of 16 bit) and offers no additional
information.
\end{ibox}
\section{Vectors and matrices}
Vectors and matrices are the most important data structures in
\matlab{}. In other programming languages there is no distinction
between theses structures, they are one- or multidimensional
\enterm{arrays}. Such arrays are structures that can store multiple
values of the same data type in a single variable. Due to \matlab{}'s
origin in the handling of mathematical problems, they have different
name but are internally the same. Vectors are 2-dimensional matrices
in which one dimension has the size 1 (a singleton dimension).
\subsection{Vectors}
In contrast to variables that store just a single value
(\enterm{scalar}) a vector can store multiple values of the same data
type (figure~\ref{vectorfig}). The variable \varcode{a} for example stores four integer values.
\begin{figure}
\includegraphics[width=0.8\columnwidth]{scalarArray}
\titlecaption{Scalars and vectors.}{\textbf{A)} A scalar variable
holds exactly on value. \textbf{B)} A vector can hold multiple
values. These must be of the same data type (e.g. integer
numbers). \matlab{} distinguishes between row- and
column-vectors.}\label{vectorfig}
\end{figure}
The following listing (\ref{generatevectorslisting} shows how vectors
can be created. In lines 5 and 9 the \code[Operator!Matrix!:]{:}
notation is used to easily create vectors with many elements or with
step-sizes unequal to 1. Line 5 can be read like: ``Create a variable
\varcode{b} and assign the values from 0 to 9 in increasing steps of
1.''. Line 9 reads: ``Create a variable \varcode{c} and assign the
values from 0 to 10 in steps of 2''.
\begin{lstlisting}[label=generatevectorslisting, caption={Creating simple row-vectors.}]
>> a = [0 1 2 3 4 5 6 7 8 9] % Creating a row-vector
a =
0 1 2 3 4 5 6 7 8 9
>> b = (0:9) % more comfortable
b =
0 1 2 3 4 5 6 7 8 9
>> c = (0:2:10)
c =
0 2 4 6 8 10
\end{lstlisting}
The length of a vector, that is the number of elements, can be
requested using the \code{length()} or \code{numel()}
functions. \code{size()} provides the same information in a slightly,
yet more powerful way (listing~\ref{vectorsizelisting}). The above
used vector \varcode{a} has the following size:
\begin{lstlisting}[label=vectorsizeslisting, caption={Size of a vector.}]
>> length(a)
ans =
10
>> size(a)
ans =
1 10
\end{lstlisting}
The answer provided by the \code{size()} function demonstrates that
vectors are nothing else but 2-dimensional matrices in which one
dimension has the size 1 (singleton dimension).
\code[length()]{length(a)} in line 1 just returns the size of the
largest dimension. Listing~\ref{columnvectorlisting} shows how to
create a column-vector and how the \code[Operator!Matrix!']{'} ---
operator is used to transpose the column-vector into a row-vector
(lines 14 and following).
\begin{lstlisting}[label=columnvectorlisting, caption={Column-vectors.}]
>> b = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] % Creating a column-vector
b =
1
2
...
9
10
>> length(b)
ans =
10
>> size(b)
ans =
10 1
>> b = b' % Transpose
b =
1 2 3 4 5 6 7 8 9 10
>> size(b)
ans =
1 10
\end{lstlisting}
\subsubsection{Accessing elements of a vector}
\begin{figure}
\includegraphics[width=0.4\columnwidth]{arrayIndexing}
\titlecaption{Index.}{Each element of a vector can be addressed via
its index (small numbers) to access its content (large
numbers).}\label{vectorindexingfig}
\end{figure}
The content of a vector is accessed using the element's index
(figure~\ref{vectorindexingfig}). Each element has an individual
\codeterm{index} that ranges (int \matlab{}) from 1 to the number of
elements irrespective of the type of vector.
\begin{important}[Indexing]
Elements of a vector are accessed via their index. This process is
called \codeterm{indexing}.
In \matlab{} the first element has the index one.
The last element's index equals the length of the vector.
\end{important}
Listings~\ref{vectorelementslisting} and~\ref{vectorrangelisting} show
how the index is used to access elements of a vector. One can access
individual values by providing a single index or use the
\code[Operator!Matrix!:]{:} notation to access multiple values with a
single command.
\begin{lstlisting}[label=vectorelementslisting, caption={Access to individual elements of a vector.}]
>> a = (11:20)
a =
11 12 13 14 15 16 17 18 19 20
>> a(1) % the 1. element
ans = 11
>> a(5) % the 5. element
ans = 15
>> a(end) % the last element
ans = 20
\end{lstlisting}
\begin{lstlisting}[caption={Access to multiple elements.}, label=vectorrangelisting]
>> a([1 3 5]) % 1., 3. and 5. element
ans =
11 13 15
>> a(2:4) % all elements with the indices 2 to 4
ans =
12 13 14
>> a(1:2:end) % every second element
ans =
11 13 15 17 19
>> a(:) % all elements as row-vector
ans =
11 12 13 14 15 16 17 18 19 20
\end{lstlisting}
\begin{exercise}{vectorsize.m}{vectorsize.out}
Create a row-vector \varcode{a} with 5 elements. The return value of
\code[size()]{size(a)} is a again a vector with the length 2. How
could you find out the size of the \varcode{a} in the 2nd dimension?
\end{exercise}
\subsubsection{Operations with vectors}
Mit Vektoren kann sehr einfach gerechnet werden. Listing
\ref{vectorscalarlisting} zeigt die Verrechnung von Vektoren mit Skalaren
mit den Operatoren \code[Operator!arithmetischer!1add@+]{+},
\code[Operator!arithmetischer!2sub@-]{-},
\code[Operator!arithmetischer!3mul@*]{*},
\code[Operator!arithmetischer!4div@/]{/}
\code[Operator!arithmetischer!5powe@.\^{}]{.\^}.
\begin{lstlisting}[caption={Rechnen mit Vektoren und Skalaren.},label=vectorscalarlisting]
>> a = (0:2:8)
a =
0 2 4 6 8
>> a + 5 % Addition von einem Skalar
ans =
5 7 9 11 13
>> a - 5 % Subtraktion von einem Skalar
ans =
-5 -3 -1 1 3
>> a * 2 % Multiplikation mit einem Skalar
ans =
0 4 8 12 16
>> a / 2 % Division mit einem Skalar
ans =
0 1 2 3 4
>> a .^ 2 % Potenzierung mit einem Skalar
ans =
0 4 16 36 64
\end{lstlisting}
Bei der elementweisen Verrechnung von zwei Vektoren muss
sichergestellt werden, dass sie die gleiche L\"ange und das gleiche
Layout (Spalten- oder Zeilenvektor) haben. Addition und Subtraktion
erfolgt immer elementweise (Listing~\ref{vectoradditionlisting}).
\begin{lstlisting}[caption={Elementweise Addition und Subtraktion von
Vektoren.},label=vectoradditionlisting]
>> a = [4 9 12];
>> b = [4 3 2];
>> a + b % Addition von 2 Vektoren
ans =
8 12 14
>> a - b % Subtraktion von 2 Vektoren
ans =
0 6 10
>> c = [8 4];
>> a + c % Beide Vektoren muessen gleich gross sein!
Error using +
Matrix dimensions must agree.
>> d = [8; 4; 2];
>> a + d % Beide Vektoren muessen das gleiche Layout haben!
Error using +
Matrix dimensions must agree.
\end{lstlisting}
Bei der Multiplikation, der Division und der Potenzierung mu{\ss} mit
vorangestellem '.' angezeigt werden, dass es sich um eine
\emph{elementweise} Verarbeitung handeln soll. F\"ur diese
elementweisen Operationen kennt \matlab{} die Operatoren
\code[Operator!arithmetischer!3mule@.*]{.*},
\code[Operator!arithmetischer!4dive@./]{./} und
\code[Operator!arithmetischer!5powe@.\^{}]{.\^{}}
(Listing~\ref{vectorelemmultiplicationlisting}).
\begin{lstlisting}[caption={Elementweise Multiplikation, Division und
Potenzierung von Vektoren.},label=vectorelemmultiplicationlisting]
>> a .* b % Elementweise Multiplikation
ans =
16 27 24
>> a ./ b % Elementweise Division
ans =
1 3 6
>> a ./ b % Elementweise Potenzierung
ans =
256 729 144
>> a .* c % Beide Vektoren muessen gleich gross sein!
Error using .*
Matrix dimensions must agree.
>> a .* d % Beide Vektoren muessen das gleiche Layout haben!
Error using .*
Matrix dimensions must agree.
\end{lstlisting}
Die einfachen Operatoren \code[Operator!arithmetischer!3mul@*]{*},
\code[Operator!arithmetischer!4div@/]{/} und
\code[Operator!arithmetischer!5pow@\^{}]{\^{}} sind mit den
entsprechenden Matrixoperationen aus der linearen Algebrar belegt (Box
\ref{matrixmultiplication}). Insbesondere ist die Multiplikation eines
Zeilenvektors $\vec a$ mit einem Spaltenvektor $\vec b$ das Skalarprodukt
$\sum_i = a_i b_i$.
\begin{lstlisting}[caption={Multiplikation von Vektoren.},label=vectormultiplicationlisting]
>> a * b % Multiplikation zweier Zeilenvektoren
Error using *
Inner matrix dimensions must agree.
>> a' * b' % Multiplikation zweier Spaltenvektoren
Error using *
Inner matrix dimensions must agree.
>> a * b' % Multiplikation Zeilenvektor mit Spaltenvektor
ans =
67
>> a' * b % Multiplikation Spaltenvektor mit Zeilenvektor
ans =
16 12 8
36 27 18
48 36 24
\end{lstlisting}
\pagebreak[4]
Zum Entfernen von Elementen aus einem Vektor, wird den
entsprechenden Zellen ein leeren Wert (\code[Operator!Matrix!{[]}]{[]}) zugewiesen:
\begin{lstlisting}[label=vectoreraselisting, caption={L\"oschen von Elementen aus einem Vektor.}]
>> a = (0:2:8);
>> length(a)
ans = 5
>> a(1) = [] % loesche das erste Element
a = 2 4 6 8
>> a([1 3]) = [] % loesche das erste und dritte Element
a = 4 8
>> length(a)
ans = 2
\end{lstlisting}
Neben dem L\"oschen von Vektorinhalten k\"onnen Vektoren auch
erweitert oder zusammengesetzt werden. Auch hier muss das Layout der
Vektoren \"ubereinstimmen (Listing \ref{vectorinsertlisting}, Zeile
10). Zum Erweitern eines Vektors kann \"uber das Ende hinaus
zugewiesen werden (Zeile 20). \matlab{} erweitert dann die Variable
entsprechend. Dieser Vorgang ist rechenintensiv da der ganze Vektor
an eine neue Stelle im Arbeitsspeicher kopiert wird und sollte, soweit
m\"oglich, vermieden werden.
\begin{lstlisting}[caption={Zusammenf\"ugen und Erweitern von Vektoren.}, label=vectorinsertlisting]
>> a = [4 3 2 1];
>> b = [10 12 14 16];
>> c = [a b] % erstelle einen Vektor aus einer Liste von Vektoren
c =
4 3 2 1 10 12 14 16
>> length(c)
ans = 8
>> length(a) + length(b)
ans = 8
>> c = [a b']; % Vektorlayout muss uebereinstimmen
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
>> a(1:3) = [5 6 7] % Weise den ersten drei Elementen neue Werte zu
a =
5 6 7 1
>> a(1:3) = [1 2 3 4]; % Laenge der Vektoren muss uebereinstimmen
In an assignment A(I) = B, the number of elements in B and I must be the same.
>> a(3:6) = [1 2 3 4] % Zuweisung ueber die Laenge des Vektors hinweg
a =
5 6 1 2 3 4
\end{lstlisting}
\subsection{Matrizen}
Vektoren sind 1-dimensionale Spezialf\"alle von $n$-dimensionalen
Matrizen. Matrizen k\"onnen in \matlab{} beliebig viele Dimensionen
haben. Von praktischer Bedeutung sind allerdings nur Matrizen mit bis
zu vier Dimensionen. Meist beschr\"ankt es sich jedoch auf 2- bis 3-d
Matrizen (Abbildung \ref{matrixfig} A,B).
\begin{figure}
\includegraphics[width=0.5\columnwidth]{matrices}
\titlecaption{Matrizen.}{\textbf{A)} Eine Variable (``test'') die eine
2-dimensionale Matrize ist. \textbf{B)} Illustration einer
3-dimensionalen Matrize. Die Pfeile zeigen den Rang der
Dimensionen an.}\label{matrixfig}
\end{figure}
Erzeugt werden Matrizen sehr \"ahnlich zu den Vektoren (Listing
\ref{matrixListing}). Die Definition einer Matrize wird, wie beim
Vektor, durch \code[Operator!Matrix!{[]}]{[]} eingeschlossen. Das
Semikolon \code[Operator!Matrix!;]{;} trennt die einzelnen Zeilen der
Matrize.
\begin{lstlisting}[label=matrixListing, caption={Erzeugen von Matrizen.}]
>> a = [1 2 3; 4 5 6; 7 8 9]
>> a =
1 2 3
4 5 6
7 8 9
>> b = ones(3, 4, 2)
b(:,:,1) =
1 1 1 1
1 1 1 1
1 1 1 1
b(:,:,2) =
1 1 1 1
1 1 1 1
1 1 1 1
\end{lstlisting}
Zur Defintion von mehr-dimensionalen Matrizen ist die Notation in
Zeile 1 nicht geeignet. Es gibt allerdings eine Reihe von
Helferfunktionen, die $n$-dimensionale Matrizen erstellen k\"onnen
(z.B. \code{ones()}, Zeile 7). Die \code{cat()}-Funktion kann
mehrdimensionale Matrizen zusammenzuf\"ugen.
Um Informationen \"uber die Gr\"o{\ss}e einer Matrize zu bekommen ist
die Funktion \code{length()} nicht geeignet. Wie oben erw\"ahnt gibt sie
die Gr\"o{\ss}e der l\"angsten Dimension aus. Die \code{size()}-Funktion
gibt dagegen die L\"ange jeder Dimension als Vektor zur\"uck.
\begin{figure}
\includegraphics[width=0.9\columnwidth]{matrixIndexing}
\titlecaption{Indices von Matrizen.}{Jedes Feld einer Matrize
wird durch einen Index individuell angesprochen. Der Index setzt
sich aus so vielen Zahlen zusammen wie es Dimensionen gibt (links
2, rechts 3). Dabei steht die 1. Stelle immer f\"ur die Zeile, die
2. f\"ur die Spalte und die dritte f\"ur das Blatt,
etc.. }\label{matrixindexingfig}
\end{figure}
Der Zugriff auf Inhalte von Matrizen erfolgt \"uber den Index
(Abbildung \ref{matrixindexingfig}, Listing
\ref{matrixIndexing}). \"Ahnlich zu den Positionen in einem
Koordinatensystem wird jede Zelle einer Matrize mit einem Index
angesprochen, der aus $n$ Zahlen besteht wobei $n$ die
Dimensionalit\"at der Matrize ist. Diese Art des Zugriffs wird
\codeterm{subscript indexing} genannt. Dabei bestimmt die errste Zahl
die Zeilennumer, die zweite die Splatennumer.
\begin{lstlisting}[caption={Zugriff auf Inhalte von Matrizen,
Indizierung.}, label=matrixIndexing]
>> x=rand(3,4) % 2-D Matrix mit Zufallszahlen mit 3 Zeilen und 4 Spalten
x =
0.8147 0.9134 0.2785 0.9649
0.9058 0.6324 0.5469 0.1576
0.1270 0.0975 0.9575 0.9706
>> size(x)
ans =
3 4
>> x(1,1) % obere linke Ecke
ans =
0.8147
>> x(2,3) % Element der 2. Zeile, 3. Spalte
ans =
0.5469
>> x(1,:) % erste Zeile
ans =
0.8147 0.9134 0.2785 0.9649
>> x(:,2) % zweite Spalte
ans =
0.9134
0.6324
0.0975
\end{lstlisting}
Alternativ zum \codeterm{subscript indexing} k\"onnen die Zellen einer
Matrize auch \emph{linear} angesprochen werden (Abbildung
\ref{matrixlinearindexingfig}). Diese Art der Adressierung ist nicht
so intuitiv verst\"andlich, kann aber sehr hilfreich sein. Der lineare
Index einer Zelle reicht von 1 bis \code{numel()} Elemente. Wobei
dieser erst entlang der 1. Dimension, dann der 2., 3. etc. Dimension
ansteigt. Listing \ref{matrixLinearIndexing} zeigt ein Beispiel f\"ur
den Einsatz des linearen Indizierens, z.B. zum Ermitteln des kleinsten
Wertes in einer Matrize.
\begin{figure}
\includegraphics[width=0.9\columnwidth]{matrixLinearIndexing}
\titlecaption{Lineares Indizieren von Matrizen.}{Der Index steigt
linear von 1 bis zur Anzahl Elemente in der Matrize an. Dabei
steigt der Index zuerst entlang der ersten, zweiten, dritten und
weiterer Dimensionen an.}\label{matrixlinearindexingfig}
\end{figure}
\begin{lstlisting}[label=matrixLinearIndexing, caption={Lineares Indizieren in Matrizen.}]
>> x = randi(100, [3, 4, 5]); % 3-D Matrix mit Zufallszahlen
>> size(x)
ans =
3 4 5
>> numel(x)
ans =
60
>> min(min(min(x))) % Minimum ueber die Zeilen, Spalten, Blaetter...
ans =
4
>> min(x(:)) % oder so
ans =
4
\end{lstlisting}
\begin{ibox}[t]{\label{matrixmultiplication} Matrixmultiplikation.}
Die Matrixmuliplikation aus der linearen Algebra ist nicht eine
elementweise Multiplikation. Die Matrixmultiplikation ist nur dann
m\"oglich, wenn die Anzahl Spalten der ersten Matrize gleich der
Anzahl Zeilen in der zweiten Matrize ist. Formaler: zwei Matrizen
$\mathbf{A}$ und $\mathbf{B}$ k\"onnen mulipiziert $(\mathbf{A}
\cdot \mathbf{B})$ werden, wenn $\mathbf{A}$ die Gr\"o{\ss}e $(m \times n)$ und
$\mathbf{B}$ die Gr\"o{\ss}e $(n \times k)$ hat. Die Mulitplikation ist
m\"oglich wenn die \determ{inneren Dimensionen} $n$ gleich sind.
Dann sind die Elemente $c_{i,j}$ des Matrixprodukts $\mathbf{C} =
\mathbf{A} \cdot \mathbf{B}$ gegeben durch das Skalarprodukt jeder
Zeile von $\mathbf{A}$ mit jeder Spalte aus $\mathbf{B}$:
\[ c_{i,j} = \sum_{k=1}^n a_{i,k} \; b_{k,j} \; . \]
Die Matrixmultiplikation ist im Allgemeinen auch nicht kommutativ:
\[ \mathbf{A} \cdot \mathbf{B} \ne \mathbf{B} \cdot \mathbf{A} \; . \]
Als Beispiel betrachten wir die beiden Matrizen
\[\mathbf{A}_{(3 \times 2)} = \begin{pmatrix} 1 & 2 \\ 5 & 4 \\ -2 & 3 \end{pmatrix}
\quad \text{und} \quad \mathbf{B}_{(2 \times 2)} = \begin{pmatrix}
-1 & 2 \\ -2 & 5 \end{pmatrix} \; . \]
F\"ur das Produkt $\mathbf{A} \cdot \mathbf{B}$ stimmen die inneren
Dimensionen der Matrizen \"uberein ($(3 \times 2) \cdot (2
\times 2)$), die Matrixmultiplikation ist also m\"oglich. Nachdem
$\mathbf{A}$ drei Zeilen und $\mathbf{B}$ zwei Spalten hat, hat das
Ergebnis von $\mathbf{A} \cdot \mathbf{B}$ die Gr\"o{\ss}e $(3
\times 2)$:
\[ \mathbf{A} \cdot \mathbf{B} = \begin{pmatrix} 1 \cdot -1 + 2 \cdot -2 & 1 \cdot 2 + 2\cdot 5 \\
5 \cdot -1 + 4 \cdot -2 & 5 \cdot 2 + 4 \cdot 5\\
-2 \cdot -1 + 3 \cdot -2 & -2 \cdot 2 + 3 \cdot 5 \end{pmatrix}
= \begin{pmatrix} -5 & 12 \\ -13 & 30 \\ -4 & 11\end{pmatrix} \; . \]
Das Produkt $\mathbf{B} \cdot \mathbf{A}$ ist dagegen nicht
definiert, da die inneren Dimensionen nicht \"ubereinstimmen
($(2 \times 2) \cdot (3 \times 2)$).
\end{ibox}
Beim Rechnen mit Matrizen gelten die gleichen Regeln wie bei
Vektoren. Matrizen k\"onnen solange elementweise miteinander
verrechnet werden, wie die Dimensionalit\"aten
\"ubereinstimmen. Wichtig ist auch hier wieder die Unterscheidung
zwischen elementweiser Multiplikation
(\code[Operator!arithmetischer!3mule@.*]{.*} Operator, Listing
\ref{matrixOperations} Zeile 10) oder Matrixmultiplikation
(\code[Operator!arithmetischer!3mul@*]{*} Operator, Listing
\ref{matrixOperations} Zeile 14, 17 und 21, Box~\ref{matrixmultiplication}).
Bei der Matrixmultiplikation m\"ussen die inneren Dimensionen der Matrizen \"ubereinstimmen
(Box~\ref{matrixmultiplication}).
\pagebreak[4]
\begin{lstlisting}[label=matrixOperations, caption={Zwei Arten der Multiplikation von Matrizen.}]
>> A = randi(5, [2, 3]) % 2-D Matrix
A =
1 5 3
3 2 2
>> B = randi(5, [2, 3]) % dito
B =
4 3 5
2 4 5
>> A .* B % elementweise Multiplikation
ans =
4 15 15
6 8 10
>> A * B % Matrixmultiplikation
Error using *
Inner matrix dimensions must agree.
>> A * B' % Matrixmultiplikation
ans =
34 37
28 24
>> A' * B % Matrixmultiplikation
ans =
10 15 20
24 23 35
16 17 25
\end{lstlisting}
\section{Boolesche Operationen}
Boolesche Ausdr\"ucke sind Anweisungen, die zu \codeterm{wahr} oder
\codeterm{falsch} ausgewertet werden. Man kennt sie z.B. aus der
Mengenlehre. In der Programmierung werden sie eingesetzt, um z.B. die
Beziehung zwischen Entit\"aten zu testen. Hierzu werden die
\codeterm{relationalen Operatoren} (\code[Operator!relationaler!>]{>},
\code[Operator!relationaler!<]{<},
\code[Operator!relationaler!==]{==},
\code[Operator!relationaler!"!]{!}, gr\"o{\ss}er als, kleiner als,
gleich und nicht) eingesetzt. Mehrere Ausdr\"ucke werden mittels der
\codeterm[Operator!logischer]{logischen Operatoren}
(\code[Operator!logischer!and1@\&]{\&}, \code[Operator!logischer!or1@{"|} {}]{|},
UND, ODER) verkn\"upft. Sie sind nicht nur wichtig, um
Codeabschnitte bedingt auszuf\"uhren (Verzweigungen,
\ref{controlstructsec}) sondern auch um aus Vektoren und Matrizen
bequem Elemente auszuw\"ahlen (logisches Indizieren,
\ref{logicalindexingsec}).
Die Tabellen \ref{logicalandor} zeigen die Wahrheitstabellen f\"ur das
logische UND, das logische ODER und das logische XOR
(entweder-oder). Es werden die Aussagen A und B mit dem Operator
verkn\"upft. Beim logischen UND ist der gesamte Ausdruck nur dann
wahr, wenn beide Ausdr\"ucke sich zu wahr auswerten lassen. Anders
ist das beim logischen ODER. Hier ist der gesamte Ausdruck wahr, wenn
sich der eine \emph{oder} der andere Ausdruck, oder beide Ausdr\"ucke
zu wahr auswerten lassen. Das auschlie{\ss}ende ODER (XOR) ist nur
wahr, wenn entweder der eine oder der andere Ausdruck wahr ist und ist
in \matlab{} als Funktion \code[xor()]{xor(A, B)} verf\"ugbar.
\begin{table}[tp]
\titlecaption{Wahrheitstabellen logisches UND, ODER und XOR.}{}\label{logicalandor}
\begin{tabular}{llll}
\multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\
& \sffamily{\textbf{und}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4}
\multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} \erb \\
& \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{red}{falsch}} & \textcolor{red}{falsch}
\end{tabular}
\hfill
\begin{tabular}{llll}
\multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\
& \sffamily{\textbf{oder}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4}
\multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{mygreen}{wahr}} & \textcolor{mygreen}{wahr} \erb \\
& \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch}
\end{tabular}
\hfill
\begin{tabular}{llll}
\multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\
& \sffamily{\textbf{xor}} & \multicolumn{1}{|c}{wahr} & falsch \\ \cline{2-4}
\multirow{2}{*}{\textbf{A}} & \multicolumn{1}{l|}{wahr} & \multicolumn{1}{c}{\textcolor{red}{falsch}} & \textcolor{mygreen}{wahr} \erb \\
& \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch}
\end{tabular}
\end{table}
Tabelle \ref{logicalrelationaloperators} zeigt die logischen Operatoren, die in
\matlab{} definiert sind. Zu bemerken sind hier noch die
\code[Operator!logischer!and2@\&\&]{\&\&} und
\code[Operator!logischer!or2@{"|}{"|} {}]{||} Operatoren. Man kann
beliebige Ausdr\"ucke verkn\"upfen und h\"aufig kann schon anhand des
ersten Ausdrucks entschieden werden, ob der gesamte boolesche Ausdruck
zu wahr oder falsch ausgewertet werden wird. Wenn zwei Aussagen mit
einem UND verkn\"upft werden und der erste zu falsch ausgewertet wird,
muss der zweite gar nicht mehr gepr\"uft werden. Die Verwendung der
\enterm{short-circuit} Versionen spart Rechenzeit, da die Ausdr\"ucke
nur sowei wie n\"otig ausgewertet werden.
\begin{table}[t]
\titlecaption{\label{logicalrelationaloperators}
Logische (links) und relationale (rechts) Operatoren in \matlab.}{}
\begin{tabular}{cc}
\hline
\textbf{Operator} & \textbf{Beschreibung} \erh \\ \hline
\varcode{$\sim$} & logisches NICHT \erb \\
\varcode{$\&$} & logisches UND\\
\varcode{$|$} & logisches ODER\\
\varcode{$\&\&$} & short-circuit logisches UND\\
\varcode{$\|$} & short-circuit logisches ODER\\
\hline
\end{tabular}
\hfill
\begin{tabular}{cc}
\hline
\textbf{Operator} & \textbf{Beschreibung} \erh \\ \hline
\varcode{$==$} & gleich \erb \\
\varcode{$\sim=$} & ungleich\\
\varcode{$>$} & gr\"o{\ss}er als \\
\varcode{$<$} & kleiner als \\
\varcode{$>=$} & gr\"o{\ss}er oder gleich \\
\varcode{$<=$} & kleiner oder gleich \\
\hline
\end{tabular}
\end{table}
Um Werte miteinander zu vergleichen gibt es die
\codeterm[Operator!relationaler]{relationalen Operatoren} (Tabelle
\ref{logicalrelationaloperators}). Mit ihnen kann man auf Dinge wie
Gleichheit (\varcode{==}) gr\"o{\ss}er oder kleiner als (\varcode{>},
\varcode{<}) testen.
\begin{important}[Zuweisungs- und Gleichheitsoperator]
Der Zuweisungsoperator \code[Operator!Zuweisung!=]{=} und der
logische Operator \code[Operator!logischer!==]{==} sind zwei
grundverschiedene Dinge. Da sie umgangsprachlich gleich sind
k\"onnen sie leider leicht verwechselt werden.
\end{important}
Das Ergebnis eines booleschen Ausdrucks ist immer vom Datentyp
\codeterm{logical}. Jede beliebige Variable zu wahr oder falsch
ausgewertet werden indem diese in den Typ \code{logical} umgewandelt
wird. Dabei werden von \matlab{} alle Werte, die nicht 0 sind als wahr
eingesch\"atzt. Listing \ref{booleanexpressions} zeigt einige
Beispiele. \matlab{} kennt die Schl\"usselworte \code{true} und
\code{false}. Diese sind Synonyme f\"ur die \code{logical} Werte 1 und
0.
\begin{lstlisting}[caption={Boolesche Ausdr\"ucke.}, label=booleanexpressions]
>> true
ans = 1
>> false
ans = 0
>> logical(1)
ans = 1
>> 1 == true
ans = 1
>> 1 == false
ans = 0
>> logical('test')
ans = 1 1 1 1
>> 1 > 2
ans = 0
>> 1 < 2
ans = 1
>> x = [2 0 0 5 0] & [1 0 3 2 0]
x = 1 0 0 1 0
>> ~([2 0 0 5 0] & [1 0 3 2 0])
ans = 0 1 1 0 1
>> [2 0 0 5 0] | [1 0 3 2 0]
ans = 1 0 1 1 0
\end{lstlisting}
\section{Logisches Indizieren}\label{logicalindexingsec}
Einer der wichtigsten Einsatzorte f\"ur boolesche Ausdr\"ucke ist das
logische Indizieren. Logisches Indizieren ist eines der
Schl\"usselkonzepte in \matlab{}. Nur mit diesem k\"onnen
Filteroperationen auf Vektoren und Matrizen effizient durchgef\"uhrt
werden. Es ist sehr m\"achtig und, wenn es einmal verstanden wurde,
sehr intuitiv zu benuzten.
Das Grundkonzept hinter der logischen Indizierung ist, dass durch die
Verwendung eines booleschen Ausdrucks auf z.B. einen Vektor ein
logischer Vektor gleicher Gr\"o{\ss}e zur\"uckgegeben wird. Dieser
wird benutzt um die Elemente des urspr\"unglichen Vektors
auszuw\"ahlen, bei denen der logische Vektor \codeterm{wahr} ist
(Listing \ref{logicalindexing1}). Zeile 14 kann wie
folgt gelesen werden: Gib die Elemente von \varcode{x} an den
Stellen, an denen \varcode{x < 0} wahr ist, zur\"uck.
\begin{lstlisting}[caption={Beispiel logisches Indizieren.}, label=logicalindexing1]
>> x = randn(1, 6) % Zeilenvektor mit 6 Zufallszahlen
x =
-1.4023 -1.4224 0.4882 -0.1774 -0.1961 1.4193
>> % logisches Indizieren in zwei Schritten:
>> x_smaller_zero = x < 0 % logischer Vektor
x_smaller_zero =
1 1 0 1 1 0
>> elements_smaller_zero = x(x_smaller_zero) % benutzen, um zuzugreifen
elements_smaller_zero =
-1.4023 -1.4224 -0.1774 -0.1961
>> % logisches Indizieren in einem Schritten:
>> elements_smaller_zero = x(x < 0)
elements_smaller_zero =
-1.4023 -1.4224 -0.1774 -0.1961
\end{lstlisting}
\begin{exercise}{logicalVector.m}{logicalVector.out}
Erstelle einen Vektor \varcode{x} mit den Werten 0--10.
\begin{enumerate}
\item F\"uhre aus: \varcode{y = x < 5}
\item Gib den Inhalt von \varcode{y} auf dem Bildschirm aus.
\item Was ist der Datentyp von \varcode{y}?
\item Gibt alle Elemente aus \varcode{x} zur\"uck, die kleiner als 5 sind.
\end{enumerate}
\pagebreak[4]
\end{exercise}
\begin{figure}[t]
\includegraphics[width= 0.9\columnwidth]{logicalIndexingTime}
\titlecaption{Beispiel f\"ur logisches Indizieren.}
{Der rot markierte Abschnitt aus den Daten wurde indirekt
mit logischem Indizieren auf dem Zeitvektor
ausgew\"ahlt (\varcode{x(t > 5 \& t < 6)}).}\label{logicalindexingfig}
\end{figure}
Logisches Indizieren wurde oben so benutzt, dass die Auswahl auf dem
Inhalt desselben Vektors beruhte. Ein weiterer sehr h\"aufiger Fall
ist jedoch, dass die Auswahl aus einem Vektor auf dem Inhalt eines
zweiten Vektors basiert. Ein Beispiel ist, dass \"uber einen
gewissen Zeitraum Daten aufgenommen werden und aus diesen die Daten eines
bestimmten Zeitraums ausgew\"ahlt werden sollen (\figref{logicalindexingfig}).
\begin{exercise}{logicalIndexingTime.m}{}
Angenommen es werden \"uber einen bestimmten Zeitraum Messwerte
genommen. Bei solchen Messungen erh\"alt man einen Vektor, der die
Zeitpunkte der Messung speichert und einen zweiten mit den
jeweiligen Messwerten.
\begin{itemize}
\item Erstelle einen Vektor \varcode{t = 0:0.001:10;}, der die Zeit
repr\"asentiert.
\item Erstelle einen zweiten Vektor \varcode{x} mit Zufallszahlen, der
die gleiche L\"ange hat wie \varcode{t}. Die Werte darin stellen
Messungen zu den Zeitpunkten in \varcode{t} dar.
\item Benutze logische Indizieren um die Messwerte
auszuw\"ahlen, die dem zeitlichen Abschnitt 5--6\,s entsprechen.
\end{itemize}
\end{exercise}
\section{Kontrollstrukturen}\label{controlstructsec}
In der Regel wird ein Programm Zeile f\"ur Zeile von oben nach unten
ausgef\"uhrt. Manchmal muss der Kontrollfluss aber so gesteuert
werden, dass bestimmte Teile wiederholt oder nur
unter bestimmten Bedingungen ausgef\"uhrt werden sollen. Von gro{\ss}er
Bedeutung sind hier zwei Strukturen:
\begin{enumerate}
\item Schleifen.
\item Bedingte Anweisungen und Verzweigungen.
\end{enumerate}
\subsection{Schleifen}
Schleifen werden gebraucht um wiederholte Ausf\"uhrung desselben Codes
zu vereinfachen. In einer \"Ubung wurde die Fakult\"at von 5 wie in
Listing \ref{facultylisting} berechnet:
\begin{lstlisting}[caption={Berechnung der Fakult\"at von 5 in f\"unf
Schritten}, label=facultylisting]
>> x = 1;
>> x = x * 2;
>> x = x * 3;
>> x = x * 4;
>> x = x * 5;
>> x
x =
120
\end{lstlisting}
Im Prinzip ist das obige Programm v\"ollig in Ordnung. Es f\"allt
jedoch auf, dass die Zeilen 2 bis 5 sehr \"ahnlich sind; bis auf die
Multiplikation mit einer ansteigenden Zahl \"andert sich nichts. Die
Verwendung von mehr oder weniger exakten Wiederholungen einzelner
Zeilen oder ganzer Abschnitte ist schlechter Prgrammierstil. Dabei
geht es nicht nur um einen \"asthetischen Aspekt sondern vielmehr
darum, dass es schwerwiegende Nachteile gibt:
\begin{enumerate}
\item Fehleranf\"alligkeit: Beim ``Copy-and-paste'' kann leicht
vergessen werden in einzelnen Wiederholungen die entscheidende
\"Anderung auch wirklich vorzunehmen.
\shortquote{Copy and paste is a design error.}{David Parnas}
\item Flexibilit\"at: Das obige Programm ist f\"ur genau einen Zweck,
Berechnung der Fakult\"at von f\"unf, gemacht und kann nichts
anderes.
\item Wartung: Wenn ein Fehler gemacht wurde, dann muss der Fehler in
allen Wiederholungen korrigiert werden (sehr leicht wird dabei etwas
\"ubersehen).
\item Verst\"andlichkeit: Solche Abschnitte sind schwerer zu lesen und
schwer zu verstehen. Das liegt zum Teil daran, dass man dazu neigt
\"uber sich wiederholende Zeilen zu springen (ist ja eh das
gleiche...) und dann den entscheidenden Teil verpasst. Zum Anderen
f\"uhrt Codeduplication zu langen, un\"ubersichtlichen Programmen.
\end{enumerate}
Alle Programmiersprachen bieten zur L\"osung dieses Problems die
Schleifen. Eine Schleife wird immer dann eingesetzt, wenn
Abschnitte wiederholt ausgef\"uhrt werden sollen.
\subsubsection{Die \code{for} -- Schleife}
Der am h\"aufigsten benutzte Vertreter der Schleifen ist die
\codeterm{for-Schleife}. Sie besteht aus dem
\codeterm[Schleife!Schleifenkopf]{Schleifenkopf} und dem
\codeterm[Schleife!Schleifenk{\"o}rper]{Schleifenk\"orper}. Der Kopf
regelt, wie h\"aufig der Code im K\"orper ausgef\"uhrt wird. Der
Schleifenkopf beginnt mit dem Schl\"usselwort \code{for} auf welches
folgend die \codeterm{Laufvariable} definiert wird. In \matlab
``l\"auft''/iteriert eine for-Schleife immer(!) \"uber einen
Vektor. Die \codeterm{Laufvariable} nimmt mit jeder Iteration einen
Wert dieses Vektors an. Im Schleifenk\"orper k\"onnen beliebige
Anweisungen ausgef\"uhrt werden. Die Schleife wird durch das
Schl\"usselwort \code{end} beendet. Listing \ref{looplisting} zeigt
das Grundger\"ust einer for-Schleife.
\begin{lstlisting}[caption={Beispiel einer \varcode{for}-Schleife.}, label=looplisting]
>> for x = 1:3
x
end
% die Laufvariable x nimmt mit jeder Iteration der Schleife
% einen Wert des Vektors 1:3 an:
1
2
3
\end{lstlisting}
\begin{exercise}{facultyLoop.m}{facultyLoop.out}
Wie k\"onnte Fakult\"at mit einer Schleife implementiert werden?
Implementiere eine \code{for} Schleife, die die Fakul\"at von einer
Zahl \varcode{n} berechnet.
\end{exercise}
\subsubsection{Die \varcode{while} -- Schleife}
Eine weiterer Schleifentyp, der weniger h\"aufig eingesetzt wird, ist
die \code{while}-Schleife. Auch sie hat ihre Entsprechungen in fast
allen Programmiersprachen. \"Ahnlich zur \code{for} Schleife wird
auch hier der in der Schleife definierte Programmcode iterativ
ausgef\"uhrt. Der Schleifenkopf beginnt mit dem Schl\"usselwort
\code{while} gefolgt von einem booleschen Ausdruck. Solange dieser zu
\code{true} ausgewertet werden kann, wird der Code im
Schleifenk\"orper ausgef\"uhrt. Die Schleife wird mit dem
Schl\"usselwort \code{end} beendet.
\begin{lstlisting}[caption={Grundstruktur einer \varcode{while} Schleife.}, label=whileloop]
while x == true
% fuehre diesen sinnvollen Code aus ...
end
\end{lstlisting}
\begin{exercise}{facultyWhileLoop.m}{}
Implementiere die Fakult\"at mit einer \code{while}-Schleife.
\end{exercise}
\begin{exercise}{neverendingWhile.m}{}
Implementiere eine \code{while}-Schleife, die unendlich
l\"auft. Tipp: wenn der boolesche Ausdruck hinter dem \code{while}
zu wahr ausgewertet wird, wird die Schleife weiter ausgef\"uhrt.
Das Programm kann mit \keycode{Ctrl+C} abgebrochen werden.
\end{exercise}
\subsubsection{Vergleich \varcode{for} -- und \varcode{while}--Schleife}
\begin{itemize}
\item Beide f\"uhren den Code im Schleifenk\"orper iterativ aus.
\item Der K\"orper einer \code{for} Schleife wird mindestens 1 mal
betreten (au{\ss}er wenn der Vektor im Schleifenkopf leer ist).
\item Der K\"orper einer \code{while} Schleife wird nur dann betreten,
wenn die Bedingung im Kopf \code{true} ist. \\$\rightarrow$ auch
``Oben-abweisende'' Schleife genannt.
\item Die \code{for} Schleife eignet sich f\"ur F\"alle in denen f\"ur
jedes Element eines Vektors der Code ausgef\"uhrt werden soll.
\item Die \code{while} Schleife ist immer dann gut, wenn nicht klar
ist wie h\"aufig etwas ausgef\"uhrt werden soll. Sie ist
speichereffizienter.
\item Jedes Problem kann mit beiden Typen gel\"ost werden.
\end{itemize}
\subsection{Bedingte Anweisungen und Verzweigungen}
Bedingte Anweisungen und Verzweigungen sind Kontrollstrukturen, die
regeln, dass der in ihnen eingeschlossene Programmcode nur unter
bestimmten Bedingungen ausgef\"uhrt wird.
\subsubsection{Die \varcode{if} -- Anweisung}
Am h\"aufigsten genutzter Vertreter ist die \code{if} -
Anweisung. Sie wird genutzt um Programmcode nur unter bestimmten
Bedingungen auszuf\"uhren.
Der Kopf der \code{if} - Anweisung beginnt mit dem Schl\"usselwort \code{if}
welches von einem booleschen Ausdruck gefolgt wird. Wenn
dieser zu \code{true} ausgewertet werden kann, wird der Code im
K\"orper der Anweisung ausgef\"uhrt. Optional k\"onnen weitere
Bedingungen mit dem Schl\"usselwort \code{elseif} folgen. Ebenfalls
optional ist die Verwendung eines finalen \code{else} - Falls. Dieser
wird immer dann ausgef\"uhrt wenn alle vorherigen Bedingungen nicht
erf\"ullt wurden. Die \code{if} - Anweisung wird mit \code{end}
beendet. Listing \ref{ifelselisting} zeigt den Aufbau einer
\code{if} - Anweisung.
\begin{lstlisting}[label=ifelselisting, caption={Grundger\"ust einer \varcode{if} Anweisung.}]
if x < y
% fuehre diesen code aus wenn x < y
elseif x > y
% etwas anderes soll getan werden fuer x > y
else
% wenn x == y, wieder etwas anderes
end
\end{lstlisting}
\begin{exercise}{ifelse.m}{}
Ziehe eine Zufallszahl und \"uberpr\"ufe mit einer geeigneten \code{if} Anweisung, ob sie
\begin{enumerate}
\item kleiner als 0.5 ist.
\item kleiner oder gr\"o{\ss}er-gleich 0.5 ist.
\item (i) kleiner als 0.5, (ii) gr\"o{\ss}er oder gleich 0.5 aber kleiner
als 0.75 oder (iii) gr\"o{\ss}er oder gleich 0.75 ist.
\end{enumerate}
\end{exercise}
\subsubsection{Die \varcode{switch} -- Verzweigung}
Die \code{switch} Verzweigung wird eingesetzt wenn mehrere F\"alle
auftreten k\"onnen, die einer unterschiedlichen Behandlung bed\"urfen.
Sie wird mit dem Schl\"usselwort \code{switch} begonnen, gefolgt von der
\codeterm{switch Anweisung} (Zahl oder String). Jeder Fall, auf den diese
Anweisung \"uberpr\"uft werden soll, wird mit dem Schl\"usselwort
\code{case} eingeleitet. Dieses wird gefolgt von der \codeterm{case
Anweisung}, die definiert gegen welchen Fall auf
Gleichheit getestet wird. F\"ur jeden Fall wird der
Programmcode angegeben, der ausgef\"uhrt werden soll. Optional k\"onnen
mit dem Schl\"usselwort \code{otherwise} alle nicht explizit genannten
F\"alle behandelt werden. Die \code{switch} Anweisung wird mit
\code{end} beendet (z.B. in Listing \ref{switchlisting}).
\begin{lstlisting}[label=switchlisting, caption={Grundger\"ust einer \varcode{switch} Anweisung.}]
mynumber = input('Enter a number:');
switch mynumber
case -1
disp('negative one');
case 1
disp('positive one');
otherwise
disp('something else');
end
\end{lstlisting}
Wichtig ist hier, dass in jedem \code{case} auf Gleichheit der
switch-Anweisung und der case-Anweisung getestet wird.
\subsubsection{Vergleich \varcode{if} -- Anweisung und \varcode{switch} -- Verzweigung}
\begin{itemize}
\item Mit der \code{if} Anweisung k\"onnen beliebige F\"alle
unterschieden und entsprechender Code ausgef\"uhrt werden.
\item Die \code{switch} Anweisung leistet \"ahnliches allerdings wird in
jedem Fall auf Gleichheit getestet.
\item Die \code{switch} Anweisung ist etwas kompakter, wenn viele F\"alle
behandelt werden m\"ussen.
\item Die \code{switch} Anweisung wird deutlich seltener benutzt und
kann immer durch eine \code{if} Anweisung erstezt werden.
\end{itemize}
\subsection{Die Schl\"usselworte \code{break} und \code{continue}}
Soll die Ausf\"uhrung einer Schleife abgebrochen oder \"ubersprungen
werden, werden die Schl\"usselworte \code{break} und
\code{continue} eingesetzt (Listings \ref{continuelisting}
und \ref{continuelisting} zeigen, wie sie eingesetzt werden k\"onnen).
\begin{lstlisting}[caption={Abbrechen von Schleifen mit \varcode{break}.}, label=breaklisting]
>> x = 1;
while true
if (x > 3)
break;
end
disp(x);
x = x + 1;
end
% output:
1
2
3
\end{lstlisting}
\begin{lstlisting}[caption={\"Uberspringen von Code-Abschnitten in Schleifen mit \varcode{continue}.}, label=continuelisting]
for x = 1:5
if(x > 2 & x < 5)
continue;
end
disp(x);
end
% output:
1
2
5
\end{lstlisting}
\begin{exercise}{logicalIndexingBenchmark.m}{logicalIndexingBenchmark.out}
Vergleich von logischem Indizieren und ``manueller'' Auswahl von
Elementen aus einem Vektor. Es wurde oben behauptet, dass die
Auswahl von Elementen mittels logischem Indizieren effizienter
ist. Teste dies indem ein Vektor mit vielen (100000) Zufallszahlen
erzeugt wird aus dem die Elemente gefiltert und gespeichert werden,
die kleiner $0.5$ sind. Umgebe den Programmabschnitt mit den
Br\"udern \code{tic} und \code{toc}. Auf diese Weise misst \matlab{}
die zwischen \code{tic} und \code{toc} vergangene Zeit.
\begin{enumerate}
\item Benutze eine \code{for} Schleife um die Elemente auszuw\"ahlen.
\item Benutze logisches Indizieren.
\end{enumerate}
\end{exercise}
\begin{exercise}{simplerandomwalk.m}{}
Programmiere einen 1-D random walk. Ausgehend von der Startposition
$0$ ``l\"auft'' ein Agent zuf\"allig in die eine oder andere
Richtung.
\begin{itemize}
\item In dem Programm sollen 10 Realisationen eines random walk mit
jeweils 1000 Schritten durchgef\"uhrt werden.
\item Die Position des Objektes ver\"andert sich in jedem Schritt zuf\"allig um
$+1$ oder $-1$.
\item Merke Dir alle Positionen.
\item Plotte die Positionen als Funktion der Schrittnummer.
\end{itemize}
\end{exercise}
\section{Skripte und Funktionen}
\subsection{Was ist ein Programm?}
Ein Programm ist eine Sammlung von Anweisungen, die in einer Datei auf
dem Rechner abgelegt sind. Wenn es durch den Aufruf zum Leben erweckt
wird, dann wird es Zeile f\"ur Zeile von oben nach unten ausgef\"uhrt.
\matlab{} kennt drei Arten von Programmen:
\begin{enumerate}
\item \codeterm[Skript]{Skripte}
\item \codeterm[Funktion]{Funktionen}
\item \codeterm[Objekt]{Objekte} (werden wir hier nicht behandeln)
\end{enumerate}
Alle Programme werden in den sogenannten \codeterm{m-files} gespeichert
(z.B. \file{meinProgramm.m}). Um sie zu benutzen werden sie von der
Kommandozeile aufgerufen oder in anderen Programmen
verwendet. Programme erh\"ohen die Wiederverwertbarkeit von
Programmcode. Bislang haben wir ausschlie{\ss}lich Skripte
verwendet. Dabei wurde jede Variable, die erzeugt wurde im
\codeterm{Workspace} abgelegt und konnte wiederverwendet werden. Hierin
liegt allerdings auch eine Gefahr. In der Regel sind Datenanalysen auf
mehrere Skripte verteilt und alle teilen sich den gemeinsamen
Workspace. Verwendet nun ein aufgerufenes Skript eine bereits
definierte Variable und weist ihr einen neuen Wert zu, dann kann das
erw\"unscht und praktisch sein. Wenn es aber unbeabsichtigt passiert
kann es zu Fehlern kommen, die nur sehr schwer erkennbar sind, da ja
jedes Skript f\"ur sich enwandtfrei arbeitet. Eine L\"osung f\"ur
dieses Problem bieten die \codeterm[Funktion]{Funktionen}.
\subsection{Funktionen}
Eine Funktion in \matlab{} wird \"ahnlich zu einer mathematischen
Funktion definiert:
\[ y = f(x) \]
Die Funktion hat einen Namen $f$, sie \"uber das Argument $x$
einen Input und liefert ein Ergebnis in $y$ zur\"uck. Listing
\ref{functiondefinitionlisting} zeigt wie das in \matlab{} umgesetzt
wird.
\begin{lstlisting}[caption={Funktionsdefinition in \matlab{}}, label=functiondefinitionlisting]
function [y] = functionName(arg_1, arg_2)
% ^ ^ ^
% Rueckgabewert Argument_1, Argument_2
\end{lstlisting}
Ein Funktion beginnt mit dem Schl\"usselwort \code{function} gefolgt
von den R\"uckgabewerte(n), dem Funktionsnamen und (in Klammern) den
Argumenten. Auf den Funktionskopf folgt der auszuf\"uhrende
Programmcode im Funktionsk\"orper. Die Funktionsdefinition wird
% optional %XXX es ist vielleicht optional, aber gute stil ware es immer hinzuschreiben, oder?
mit einem \code{end} abgeschlossen. Jede Funktion, die vom
Nutzer direkt verwendet werden soll, ist in einer eigenen Datei
definiert. \"Uber die Definition/Benutzung von Funktionen wird folgendes erreicht:
\begin{itemize}
\item Kapseln von Programmcode, der f\"ur sich eine Aufgabe l\"ost.
\item Definierte Schnittstelle.
\item Eigener G\"ultigkeitsbereich:
\begin{itemize}
\item Variablen im Workspace sind in der Funktion \emph{nicht} sichtbar.
\item Variablen, die in der Funktion definiert werden erscheinen
\emph{nicht} im Workspace.
\end{itemize}
\item Erh\"oht die Wiederverwendbarkeit von Programmcode.
\item Erh\"oht die Lesbarkeit von Programmen, da sie
\"ubersichtlicher werden.
\end{itemize}
Das Folgende Beispiel (Listing \ref{badsinewavelisting}) zeigt eine
Funktion, die eine Reihe von Sinusschwingungen unterschiedlicher
Frequenzen berechnet und graphisch darstellt.
\begin{lstlisting}[caption={Ein schlechtes Beispiel einer Funktion, die eine Reihe Sinusse plottet.},label=badsinewavelisting]
function meineErsteFunktion() % Funktionskopf
t = (0:0.01:2); % hier faengt der Funktionskoerper an
frequenz = 1.0;
amplituden = [0.25 0.5 0.75 1.0 1.25];
for i = 1:length(amplituden)
y = sin(frequenz * t * 2 * pi) * amplituden(i);
plot(t, y)
hold on;
end
end
\end{lstlisting}
Das obige Beispiel ist ein Paradebeispiel f\"ur eine schlechte
Funktion. Sie hat folgende Probleme:
\begin{itemize}
\item Der Name ist nicht aussagekr\"aftig.
\item Die Funktion ist f\"ur genau einen Zweck geeignet.
\item Was sie tut, ist festgelegt und kann von au{\ss}en nicht
beeinflusst oder bestimmt werden.
\item Sie tut drei Dinge auf einmal: Sinus berechnen \emph{und}
Amplituden \"andern \emph{und} graphisch darstellen.
\item Es ist nicht (einfach) m\"oglich an die berechneten Daten zu
kommen.
\item Keinerlei Dokumentation. Man muss den Code lesen und rekonstruieren, was sie tut.
\end{itemize}
Bevor wir anfangen die Funktion zu verbessern mu{\ss} definiert werden
was das zu l\"osende Problem ist:
\begin{enumerate}
\item Welches Problem soll gel\"ost werden?
\item Aufteilen in Teilprobleme.
\item Gute Namen finden.
\item Definieren der Schnittstellen --- Was m\"ussen die beteiligten Funktionen
wissen? Was sollen sie zur\"uckliefern?
\item Daten zur\"uck geben (R\"uckgabewerte definieren).
\end{enumerate}
Das Beispielproblem aus Listing \ref{badsinewavelisting} kann in drei
Teilprobleme aufgetrennt werden. (i) Berechnen der \emph{einzelnen}
Sinusse. (ii) Plotten der jeweils berechneten Daten und (iii)
Koordination von Berechnung und Darstellung mit unterschiedlichen
Amplituden.
\paragraph{I. Berechnung eines einzelnen Sinus}
Die Berechnung eines einzelnen Sinus ist ein typischer Fall f\"ur eine
Funktion. Wiederum macht man sich klar, (i) wie die Funktion
hei{\ss}en soll, (ii) welche Information sie ben\"otigt und (iii)
welche Daten sie zur\"uckliefern soll.
\begin{enumerate}
\item \codeterm[Funktion!Name]{Name}: der Name sollte beschreiben, was
die Funktion tut. In diesem Fall berechnet sie einen Sinus. Ein
geeigneter, kurzer Name w\"are also \code{sinewave()}.
\item \codeterm[Funktion!Argumente]{Argumente}: die zu brechnende
Sinusschwingung sei durch ihre Frequenz und die Amplitude
bestimmt. Des Weiteren soll noch festgelegt werden, wie lang der
Sinus sein soll und mit welcher zeitlichen Aufl\"osung gerechnet
werden soll. Es werden also vier Argumente ben\"otigt, sie k\"onnten
hei{\ss}en: \varcode{amplitude}, \varcode{frequency},
\varcode{t\_max}, \varcode{t\_step}.
\item \codeterm[Funktion!R{\"u}ckgabewerte]{R\"uckgabewerte}: Um den
Sinus korrekt darstellen zu k\"onnen brauchen wir die Zeitachse und
die entsprechenden Werte. Es werden also zwei Variablen
zur\"uckgegeben: \varcode{time}, \varcode{sine}
\end{enumerate}
Mit dieser Information ist es nun gut m\"oglich die Funktion zu
implementieren (Listing \ref{sinefunctionlisting}).
\begin{lstlisting}[caption={Funktion zur Berechnung eines Sinus.}, label=sinefunctionlisting]
function [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
% Calculate a sinewave of a given frequency, amplitude,
% duration and temporal resolution.
%
% [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
%
% Arguments:
% frequency: the frequency of the sine
% amplitude: the amplitude of the sine
% t_max : the duration of the sine in seconds
% t_step : the temporal resolution in seconds
% Returns:
% time: vector of the time axis
% sine: vector of the calculated sinewave
time = (0:t_step:t_max);
sine = sin(frequency .* time .* 2 * pi) .* amplitude;
end
\end{lstlisting}
\paragraph{II. Plotten einer einzelnen Schwingung}
Das Plotten der berechneten Sinuschwingung kann auch von einer
Funktion \"ubernommen werden. Diese Funktion hat keine andere Aufgabe,
als die Daten zu plotten. Ihr Name sollte sich an dieser Aufgabe
orientieren (z.B. \code{plotFunction()}). Um einen einzelnen Sinus
zu plotten werden im Wesentlichen die x-Werte und die zugeh\"origen
y-Werte ben\"otigt. Da mehrere Sinus geplottet werden sollen ist es
auch sinnvoll eine Zeichenkette f\"ur die Legende an die Funktion zu
\"ubergeben. Da diese Funktion keine Berechnung durchf\"uhrt wird kein
R\"uckgabewert ben\"otigt (Listing \ref{sineplotfunctionlisting}).
\begin{lstlisting}[caption={Funktion zur graphischen Darstellung der Daten.}, label=sineplotfunctionlisting]
function plotFunction(x_data, y_data, name)
% Plots x-data against y-data and sets the display name.
%
% plotFunction(x_data, y_data, name)
%
% Arguments:
% x_data: vector of the x-data
% y_data: vector of the y-data
% name : the displayname
plot(x_data, y_data, 'displayname', name)
end
\end{lstlisting}
\paragraph{III. Erstellen eines Skriptes zur Koordinierung}
Die letzte Aufgabe ist die Koordinierung der Berechung und des
Plottens f\"ur mehrere Amplituden. Das ist die klassische Aufgabe
f\"ur ein \codeterm{Skript}. Auch hier gilt es einen ausdrucksvollen
Name zu finden. Da es keine Argumente und R\"uckgabewerte gibt,
m\"ussen die ben\"otigten Informationen direkt in dem Skript
defniniert werden. Es werden ben\"otigt: ein Vektor f\"ur die
Amplituden, je eine Variable f\"ur die gew\"unschte Frequenz, die
maximale Zeit auf der x-Achse und die zeitliche Aufl\"osung. Das
Skript \"offnet schlie{\ss}lich noch eine neue Abbildung mit
\code{figure()} und setzt das \code{hold on} da nur das Skript
wei{\ss}, das mehr als ein Plot erzeugt werden soll. Das Skript ist in
Listing \ref{sinesskriptlisting} dargestellt.
\begin{lstlisting}[caption={Kontrollskript zur Koordination von Berechnung und graphischer Darstellung.},label=sinesskriptlisting]
amplitudes = 0.25:0.25:1.25;
frequency = 2.0;
t_max = 10.0;
t_step = 0.01;
figure()
hold on
for i = 1:length(amplitudes)
[x_data, y_data] = sinewave(frequency, amplitudes(i), ...
t_max, t_step);
plotFunction(x_data, y_data, sprintf('freq: %5.2f, ampl: %5.2f',...
frequency, amplitudes(i)))
end
hold off
legend('show')
\end{lstlisting}
\begin{exercise}{plotMultipleSinewaves.m}{}
Erweiter das Programm so, dass die Sinusse f\"ur einen Satz von
Frequenzen geplottet wird.
\pagebreak[4]
\end{exercise}
\subsection{Einsatz von Funktionen und Skripten}
Funktionen sind kleine Codefragmente, die im Idealfall genau eine
Aufgabe erledigen. Sie besitzen einen eigenen
\determ{G\"ultigkeitsbereich}, das hei{\ss}t, dass Variablen aus dem
globalen Workspace nicht verf\"ugbar sind und Variablen, die lokal in
der Funktion erstellt werden nicht im globalen Workspace sichtbar
werden. Dies hat zur Folge, dass Funktionen all die Informationen, die
sie ben\"otigen, von au{\ss}en erhalten m\"ussen. Sie nehmen
\determ{Argumente} entgegen und k\"onnen \determ{R\"uckgabwerte}
zur\"uckliefern.
Die Verwendung von Funktionen ist der Verwendung von Skripten fast
immer vorzuziehen sind. Das hei{\ss}t aber nicht, das Skripte zu
verteufeln w\"aren und und vermieden werden sollten. In Wahrheit sind
beide daf\"ur gemacht, Hand in Hand ein Problem zu l\"osen. W\"ahrend
die Funktionen relativ kleine ``verdauliche'' Teilprobleme l\"osen,
werden Skripte eingesetzt um den Rahmen zu bilden und den Ablauf zu
koordinieren (Abbildung \ref{programlayoutfig}).
\begin{figure}
\includegraphics[width=0.5\columnwidth]{simple_program.pdf}
\titlecaption{Ein typisches Programmlayout.}{Das Kontrollskript
koordiniert den Aufruf der Funktionen, \"ubergibt Argumente und
nimmt R\"uckgabewerte entgegen.}\label{programlayoutfig}
\end{figure}