From 67888b398175b7a5f829e3e4667ef7bcd1ab7a51 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Sun, 9 Oct 2016 13:51:06 +0200 Subject: [PATCH] copy rest of chap1 to german version --- programming/lecture/programming_de.tex | 1319 ++++++++++++++++++++++++ 1 file changed, 1319 insertions(+) diff --git a/programming/lecture/programming_de.tex b/programming/lecture/programming_de.tex index d11183a..d7d3d93 100644 --- a/programming/lecture/programming_de.tex +++ b/programming/lecture/programming_de.tex @@ -208,3 +208,1322 @@ den Datentypen auseinanderzusetzen (Box \ref{daqbox}). und bietet keine zus\"atzliche Information. \end{ibox} + +\section{Vektoren und Matrizen} + +Vektoren und Matrizen sind die wichtigsten Datenstrukturen in +\matlab{}. In anderen Programmiersprachen hei{\ss}en sie ein- +bzw. mehrdimensionalen Felder. Felder sind Datenstrukturen, die +mehrere Werte des gleichen Datentyps in einer Variablen vereinen. Da +\matlab{} seinen Ursprung in der Verarbeitung von mathematischen +Vektoren und Matrizen hat, werden sie hier auch so genannt. Dabei +macht \matlab{} intern keinen Unterschied zwischen Vektoren und +Matrizen. Vektoren sind 2--dimensionale Matrizen, bei denen eine +Dimension die Gr\"o{\ss}e 1 hat. + + +\subsection{Vektoren} + +Im Gegensatz zu Variablen, die einzelene Werte beinhalten +(Skalare), kann ein Vektor mehrere Werte des gleichen Datentyps +beinhalten (Abbildung \ref{vectorfig} B). Die Variable \varcode{a} +enth\"alt im Beispiel in Abbildung \ref{vectorfig} vier ganzzahlige Werte. + +\begin{figure} + \includegraphics[width=0.8\columnwidth]{scalarArray} + \titlecaption{Skalare und Vektoren.}{\textbf{A)} Eine skalare Variable kann + genau einen Wert tragen. \textbf{B)} Ein Vektor kann mehrer + Werte des gleichen Datentyps (z.B. ganzzahlige Integer Werte) + beinhalten. \matlab{} kennt den Zeilen- (row-) und Spaltenvektoren + (columnvector).}\label{vectorfig} +\end{figure} + +Das folgende Listing \ref{generatevectorslisting} zeigt, wie Vektoren erstellt +werden k\"onnen. + +\begin{lstlisting}[label=generatevectorslisting, caption={Erstellen einfacher Zeilenvektoren.}] +>> a = [0 1 2 3 4 5 6 7 8 9] % Erstellen eines Zeilenvektors +a = + 0 1 2 3 4 5 6 7 8 9 + +>> b = (0:9) % etwas bequemer +b = + 0 1 2 3 4 5 6 7 8 9 + +>> c = (0:2:10) +c = + 0 2 4 6 8 10 +\end{lstlisting} +Die L\"ange eines Vektors, d.h. die Anzahl der Elemente des Vektors, +kann mithilfe der Funktionen \code{length()} und \code{numel()} +bestimmt werden. \"Ahnliche Information kann \"uber die Funktion +\code{size()} erhalten werden (Listing \ref{vectorsizeslisting}). Der +Vektor \varcode{a} von oben hat folgende Gr\"o{\ss}en: + +\begin{lstlisting}[label=vectorsizeslisting, caption={Gr\"o{\ss}e von Vektoren.}] +>> length(a) +ans = + 10 +>> size(a) +ans = + 1 10 +\end{lstlisting} + +Die Ausgabe der \code{size()}-Funktion zeigt, dass Vektoren im Grunde +2-dimensional sind. Bei einem Zeilenvektor hat die erste Dimension die +Gr\"o{\ss}e 1. \code[length()]{length(a)} gibt die l\"angste +Ausdehnung an. Im folgenden Listing \ref{columnvectorlisting} transponiert der +\code[Operator!Matrix!']{'} - Operator einen Spaltenvektor +zu einem Zeilenvektor (Zeilen 14 ff.). + +\begin{lstlisting}[label=columnvectorlisting, caption={Spaltenvektoren.}] +>> b = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] % Erstellen eines Spaltenvektors +b = + 1 + 2 + ... + 9 + 10 + +>> length(b) +ans = + 10 +>> size(b) +ans = + 10 1 + +>> b = b' % Transponieren +b = + 1 2 3 4 5 6 7 8 9 10 + +>> size(b) +ans = + 1 10 +\end{lstlisting} + + +\subsubsection{Zugriff auf Inhalte von Vektoren} +\begin{figure} + \includegraphics[width=0.4\columnwidth]{arrayIndexing} + \titlecaption{Indices von Vektoren.}{Jedes Feld eines Vektors hat + einen Index (kleine Zahl) mit dem auf den jeweiligen Inhalt + (gro{\ss}e Zahl) zugegriffen werden + kann.}\label{vectorindexingfig} +\end{figure} + +Der Zugriff auf die Inhalte eines Vektors erfolgt \"uber den Index +(Abbildung \ref{vectorindexingfig}). Jedes Feld in einem Vektor hat +einen fortlaufenden \codeterm{Index}, \"uber den auf die Werte des +Vektors zugegriffen werden kann. Dabei spielt es keine Rolle, ob es +sich um einen Zeilen- oder Spaltenvektor handelt. + +\begin{important}[Indizieren] + Der Zugriff auf Inhalte eines Vektors mittels seines Indexes wird + Indizieren genannnt. + + Der Index des ersten Elements eines Vektors ist in \matlab{} die Eins. + + Der Index des letzten Elements entspricht der L\"ange des Vektors. +\end{important} + +Die Listings \ref{vectorelementslisting} und \ref{vectorrangelisting} zeigen wie +mit Indexen auf die Inhalte eines Vektors zugegriffen werden kann. +Hierbei kann auf einzelne Werte zugegriffen werden oder, analog zur +Erzeugung von Vektoren, die \code[Operator!Matrix!:]{:} Notation +verwendet werden, um auf mehrere Element gleichzeitig zuzugreifen. + +\begin{lstlisting}[label=vectorelementslisting, caption={Zugriff auf den Inhalt von Vektoren: einzelne Elemente}] +>> a = (11:20) +a = + 11 12 13 14 15 16 17 18 19 20 + +>> a(1) % das 1. Element +ans = 11 +>> a(5) % das 5. Element +ans = 15 +>> a(end) % das letzte Element +ans = 20 +\end{lstlisting} + +\begin{lstlisting}[caption={Zugriff auf den Inhalt von Vektoren: Bereiche}, label=vectorrangelisting] +>> a([1 3 5]) % das 1., 3. und 5. Element +ans = + 11 13 15 + +>> a(2:4) % alle Elemente von Index 2 bis einschliesslich 4 +ans = + 12 13 14 + +>> a(1:2:end) % jedes zweite Element +ans = + 11 13 15 17 19 + +>> a(:) % alle Elemente als Zeilenvektor +ans = + 11 12 13 14 15 16 17 18 19 20 +\end{lstlisting} + +\begin{exercise}{vectorsize.m}{vectorsize.out} + Erstelle einen Zeilenvektor \varcode{a} mit 5 Elementen. + Der R\"uckgabewert von \code[size()]{size(a)} ist wieder ein Vektor der + L\"ange 2. Wie k\"onnte also die Gr\"o{\ss}e von \varcode{a} in der + zweiten Dimension herausgefunden werden? +\end{exercise} + +\subsubsection{Operationen auf Vektoren} + +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}