%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{\tr{Programming basics}{Programmierung in \matlab}} \section{Variablen und Datentypen} \subsection{Variablen} aEine Variable ist ein Zeiger auf eine Stelle im Speicher. Dieser Zeiger hat einen Namen, den Variablennamen, und einen Datentyp (Abbildung \ref{variablefig}). Im Speicher wird der Wert der Variablen bin\"ar gespeichert. Wird auf den Wert der Variable zugegriffen, wird dieses Bitmuster je nach Datentyp interpretiert. Das Beispiel in Abbildung \ref{variablefig} zeigt, dass das gleiche Bitmuster im einen Fall als 8-Bit Integer Datentyp zur Zahl 38 interpretiert wird und im anderen Fall als Character zum kaufm\"annischen ``und'' ausgewertet wird. In \matlab{} sind Datentypen nicht von sehr zentraler Bedeutung. Wir werden uns dennoch sp\"ater etwas genauer mit ihnen befassen. \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} \caption{\textbf{Variablen.} Variablen sind Zeiger auf eine Adresse im Speicher, die einen Namen und einen Datentypen beinhalten. Im Speicher ist der Wert der Variable bin\"ar gespeichert. Abh\"angig vom Datentyp wird dieses Bitmuster unterschiedlich interpretiert.}\label{variablefig} \end{figure} \subsection{Erzeugen von Variablen} In \matlab{} kann eine Variable auf der Kommandozeile, in einem Skript oder einer Funktion an beliebiger Stelle erzeugen. Das folgende Listing zeigt zwei M\"oglichkeiten: \begin{lstlisting}[label=varListing1, caption=Erzeugen von Variablen] >> y = [] y = [] >> >> x = 38 x = 38 \end{lstlisting} Die Zeile 1 kann etwa so gelesen werden:''Erzeuge eine Variable mit dem Namen y und weise ihr einen leeren Wert zu.'' Das Gleichheitszeichen ist der sogenannte \textit{Zuweisungsoperator}. Zeile 5 definiert eine Variable x, der nun der Zahlenwert 38 zugewiesen wird. Da \matlab{}, wenn nicht anders angegeben immer den ``double'' Datentypen benutzt, haben beide Variablen diesen Datentyp. \begin{lstlisting}[label=varListing2, caption={Erfragen des Datentyps einer Variable, Listen aller definierten Variablen.}] >>disp(class(x)) double >> >> who % oder whos um mehr Information zu bekommen \end{lstlisting} Bei der Namensgebung ist zu beachten, dass \matlab{} auf Gro{\ss}- und Kleinschreibung achtet und ein Variablennane mit einem alphabethischen Zeichen beginnen muss. Des Weiteren sind Umlaute, Sonder- und Leerzeichen in Variablennamen nicht erlaubt. \subsection{Arbeiten mit Variablen} Nat\"urlich kann mit den Variablen auch gearbeitet, bzw gerechnet werden. \matlab{} kennt alle normalen arithmetischen Operatoren wie \code{+, -, *. /}. Die Potenz wird \"uber das Dach Symbol \code{\^} dargestellt. Das folgende Listing zeigt, wie sie benutzt werden. \begin{lstlisting}[label=varListing3, caption={Rechnen mit Variablen.}] >> x = 1; >> x + 10 ans = 11 >> >> x % x wurde nicht veraendert ans = 1 >> >> y = 2; >> >> x + y ans = 3 >> >> z = x + y z = 3 >> >> z = z * 5; >> z z = 15 >> >> clear z \end{lstlisting} Beachtenswert ist z.B. in Zeilen 3 und 6, dass wir mit dem Inhalt einer Variablen rechnen k\"onnen, ohne dass dadurch ihr Wert ver\"andert wird. Wenn der Wert einer Variablen ver\"andert werden soll, dann muss dieser der Variable explizit zugewiesen werden (mit dem \code{=} Zuweisungsoperator, z.B. Zeilen 16, 20). Zeile 25 zeigt wie eine einzelne Variable gel\"oscht wird. \subsection{Datentypen} Der Datentyp bestimmt, wie die im Speicher abgelegten Bitmuster interpretiert werden. Die wichtigsten Datentpyen sind folgende: \begin{itemize} \item \textit{integer} - Ganze Zahlen. Hier gibt es mehrere Unterarten, die wir in \matlab{} (meist) ignorieren k\"onnen. \item \textit{double} - Flie{\ss}kommazahlen. Im Gegensatz zu den reelen Zahlen, die durch diesen Datentyp dargestellt werden, sind sie abz\"ahlbar. \item \textit{complex} - Komplexe Zahlen. \item \textit{logical} - Boolesche Werte, die als wahr (\textit{true}) oder falsch (\textit{false}) interpretiert werden. \item \textit{char} - ASCII Zeichen \end{itemize} Unter den numerischen Datentypen gibt es verschiedene Arten mit unterschiedlichem Speicherbedarf und Wertebreich. \begin{table}[] \centering \caption{Grundlegende Datentypen und ihr Wertebereich.} \label{dtypestab} \begin{tabular}{llcl}\hline Datentyp & Speicherbedarf & Wertebereich & Beispiel \rule{0pt}{2.5ex} \\ \hline double & 64 bit & $\approx -10^{308}$ bis $\approx 10^{308} $& Flie{\ss}kommazahlen.\rule{0pt}{2.5ex}\\ int & 64 bit & $-2^{31}$ bis $2^{31}-1$ & Ganzzahlige Werte \\ int16 & 16 bit & $-2^{15}$ bis $2^{15}-1$ & Digitalisierte Spannungen. \\ uint8 & 8 bit & $0$ bis $255$ & Digitalisierte Imaging Daten. \\ \hline \end{tabular} \end{table} \matlab{} arbeitet meist mit dem ``double'' Datentyp wenn numerische Daten gespeichert werden. Dennoch lohnt es sich, sich ein wenig mit den Datentypen auseinanderzusetzen. Ein Szenario, dass in der Neurobiologie nicht selten ist, ist, dass wir die elektrische Aktivit\"at einer Nervenzelle messen. Die gemessenen Spannungen werden mittels Messkarte digitalisiert und auf dem Rechner gespeichert. Typischerweise k\"onnen mit solchen Messkarten Spannungen im Bereich $\pm 10$\,V gemessen werden. Die Aufl\"osung der Wandler betr\"agt heutzutage meistens 16 bit. Das heisst, dass der gesamte Spannungsbereich in $2^{16}$ Schritte aufgeteilt ist. Um Speicherplatz zu sparen w\"are es sinnvoll, die gemessenen Daten als ``int16'' Werte im Rechner abzulegen. Die Daten als ``echte'' Spannungen, also als Flie{\ss}kommawerte, abzulegen w\"urde den 4-fachen Speicherplatz ben\"otigen. \section{Vektoren und Matrizen} % \begin{definition}[Vektoren und Matrizen] Vektoren und Matrizen sind die wichtigsten Datenstrukturen in \matlab. In anderen Programmiersprachen spricht man von ein- bzw. mehrdimensionalen Feldern. Felder sind Datenstrukturen, die mehrere Werte des geleichen Datentyps in einer Variablen vereinen. Da Matalb seinen Ursprung in der Verarbeitung von mathematischen Vektoren und Matrizen hat, werden sie hier auch so genannt. \matlab{} macht keinen Unterschied zwischen Vektoren und Matrizen. Vektoren sind 2-dimsensionale Matrizen bei denen eine Dimension die Gr\"o{\ss}e 1 hat. % \end{definition} \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 ``test'' enth\"alt in diesem Beispiel vier ganzzahlige Werte. \begin{figure} \includegraphics[width=0.8\columnwidth]{scalarArray} \caption{\textbf{Skalare und Vektoren. 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 Spaltenvektor (columnvector).}\label{vectorfig} \end{figure} Das folgende Listing zeigt, wie einfache Vektoren erstellt werden k\"onnen. \begin{lstlisting}[label=arrayListing1, 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 Funktion \code{length()} bestimmt werden. \"Ahnliche Information kann \"uber die Funktion \code{size()} erhalten werden. Im Falle des Vektors \code{a} von oben erh\"alt man folgende Ausgabe: \begin{lstlisting}[label=arrayListing2, caption={Gr\"o{\ss}e von Vektoren.}] >> length(a) ans = 10 >> size(a) ans = 1 10 \end{lstlisting} Diese Ausgabe zeigt, dass Vektoren im Grunde 2-dimensional sind. Bei einem Zeilenvektor hat die erste Dimension die Gr\"o{\ss}e 1. \code{length(a)} gibt die l\"angste Ausdehnung an. \begin{lstlisting}[label=arrayListing3, 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 >> size(b) ans = 1 10 \end{lstlisting} Der \code{'}- Operator transponiert den Spaltenvektor zu einem Zeilenvektor. \subsubsection{Zugriff auf Inhalte von Vektoren} \begin{figure} \includegraphics[width=0.4\columnwidth]{arrayIndexing} \caption{\textbf{Indices von Vektoren.} Jedes Feld eines Vektors hat einen Index mit dem auf den jeweiligen Inhalt 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 \textit{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. \textbf{Achtung!} Anders als viele andere Sprachen beginnt \matlab{} mit dem Index 1. Die Listings \ref{arrayListing4} und \ref{arrayListing5} zeigen wie man mit dem Index auf die Inhalte zugreifen kann. \begin{lstlisting}[label=arrayListing4, caption={Zugriff auf den Inhalt von Vektoren I}] >> a = (11:20); >> a(1) % das 1. Element ans = 11 >> a(5) % das 5. Element ans = 15 >> a(end) % das letzte Element ans = 20 \end{lstlisting} Hierbei kann auf einzelne Werte zugegriffen werden oder, analog zur Erzeugung von Vektoren, die \code{:} Notation verwendet werden, um auf mehrere Element gleichzeitig zuzugreifen. \begin{lstlisting}[caption={Zugriff auf den Inhalt von Vektoren I}, label=arrayListing5] >> 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 \end{lstlisting} \begin{exercise}{vectorsize.m}{vectorsize.out} Der R\"uckgabewert von \code{size(a)} ist wieder ein Vektor der L\"ange 2. Wie k\"onnte man also die Gr\"o{\ss}e von \code{a} in der zweiten Dimension herausfinden? \end{exercise} \subsubsection{Operationen auf Vektoren} Mit Vektoren kann sehr einfach gerechnet werden. Listing \ref{arrayListing5} zeigt Rechnungen mit Vektoren. \begin{lstlisting}[caption={Rechnen mit Vektoren.},label=arrayListing5] >> a = (0:2:8); >> a + 5 % addiere einen Skalar ans = 5 7 9 11 13 >> a - 5 % subtrahiere einen Skalar ans = -5 -3 -1 1 3 >> a .* 2 % Multiplication ans = 0 4 8 12 16 >> a ./ 2 % Division ans = 0 1 2 3 4 >> a(1:3) + a(2:4) % Addieren von 2 Vektoren ans = 2 6 10 >> >> a(1:2) + a(2:4) % Vektoren muessen gleich gross sein! ??? Error using ==> plus Matrix dimensions must agree. \end{lstlisting} Wird ein Vektor mit einem skalaren Wert verrechnet, dann ist das problemlos m\"oglich. Bei der Multiplikation (Zeile 10), der Division (Zeile 14) und auch der Potenzierung mu{\ss} mit vorangestellem '.' klar gemacht werden, dass es sich um eine \textit{elementweise} Verarbeitung handeln soll. F\"ur diese elementweisen Operationen kennt \matlab{} die Operatoren \code{.*}, \code{./} und \code{.\^}. Die einfachen Operatoren \code{*}, \code{/} und \code{\^} sind mit den entsprechenden Matrixoperationen aus der linearen Algebrar belegt (s.u.). Zu Beachten ist des Weiteren noch die Fehlermeldung am Schluss von Listing \ref{arrayListing5}. Wenn zwei Vektoren (elementweise) miteinander verrechnet werden sollen, muss nicht nur die Anzahl der Elemente übereinstimmen, sondern es muss auch das Layout (Zeilen- oder Spaltenvektoren) \"ubereinstimmen. Will man Elemente aus einem Vektor entfernen, dann weist man den entsprechenden Zellen einen leeren Wert (\code{[]}) zu. \begin{lstlisting}[label=arrayListing6, 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]) = [] 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{arrayListing7}, Zeile 12). Will man einen Vektor erweitern, kann man \"uber das Ende hinaus zuweisen. \matlab{} erweitert dann die Variable. Auch hierbei muss auf das Layout geachtet werden. Zudem ist dieser Vorgang ``rechenintensiv'' und sollte soweit m\"oglich vermieden werden. \begin{lstlisting}[caption={Zusammenf\"ugen und Erweitern von Vektoren.}, label=arrayListing7] >> a = (0:2:8); >> b = (10:2:19); >> c = [a b] % erstelle einen Vektor aus einer Liste von Vektoren c = 0 2 4 6 8 10 12 14 16 18 >> length(c) ans = 10 >> length(a) + length(b) ans = 10 >> c = [a b']; Error using horzcat Dimensions of matrices being concatenated are not consistent. >> b(6:8) = [1 2 3 4]; \end{lstlisting} \subsection{Matrizen} Im Gegesatz zu den 1-dimensionalen Vektoren k\"onnen Martizen n-dimensional sein, das hei{\ss}t, dass sie beliebig viele Dimensionen haben k\"onnen. 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} \caption{\textbf{Matrizen. 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{[]} eingeschlossen. Das \code{;} 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,3,2); >> b b(:,:,1) = 1 1 1 1 1 1 1 1 1 b(:,:,2) = 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). Sollte sich die Notwendigkeit ergeben mehrdimensionale Matrizen zusammenzuf\"ugen hilft die \code{cat} Funktion. Um Informationen \"uber die Gr\"{\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. Wann immer es um Matrizen geht, wird \code{size} benutzt. \begin{figure} \includegraphics[width=0.9\columnwidth]{matrixIndexing} \caption{\textbf{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\"uer 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 \textit{subsript indexing} genannt. \begin{lstlisting}[caption={Zugriff auf Inhalte von Matrizen, Indexierung.}, label=matrixIndexing] >> x = randi(100, [3, 4, 5]); % 3-D Matrix mit Zufallszahlen >> size(x) ans = 3 4 5 >> x(1,1,1); % obere linke Ecke ans(1,1,1) = 14 >> >> x(1,1,:) % obere linke Ecke entlang der 3. Dimension ans(1,1,:) = 14 ans(:,:,2) = 58 ans(:,:,3) = 4 ans(:,:,4) = 93 ans(:,:,5) = 56 \end{lstlisting} Alternativ zum \textit{subscript indexing} k\"onnen die Zellen einer Matrize auch \textit{linear} angesprochen werden (Abbildung \ref{matrixlinearindexingfig}). Diese Art der Adressierung ist nicht so intuituiv verst\"andlich, kann aber sehr hilfreich sein. Der ``linare'' Index einer Zelle reicht von 1 bis \code{numel(M)} Elemente. Wobei dieser erst entlang der 1. Dimension, dann der 2., 3. etc. Dimension ansteigt. Listing \ref{matrixLinearIndexing} zeigt ein Beispiel fuer den Einsatz des linearen Indexierens z.B. wenn man den Minimalwert aller Elemente einer Matrize ermitteln m\"ochte.. \begin{figure} \includegraphics[width=0.9\columnwidth]{matrixLinearIndexing} \caption{\textbf{Lineares Indexieren 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 Indexieren 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))) % Minumum uber die Zeilen, Spalten, Blaetter... ans = 4 >> min(x(:)) % oder so ans = 4 \end{lstlisting} Beim Rechnen mit Matrizen gelten die gleichen Regeln wie bei Vektoren. Matrizen k\"onnen solange elementweise miteinander Verrechnet werden, wie die Dimensionalit\"aten \"ubereinstimmen. Besondere Vorsicht sollte man immer dann walten lassen, wenn man Matrizen miteinander mulitplizieren, dividieren oder potenzieren will. Hier ist es wichtig sich klarzumachen was man will: Eine elementweise Multiplikation (\code{.*} Operator, Listing \ref{matrixOperations} Zeile 18) oder ob eine Matrixmultiplikation (\code{*} Operator, Listing \ref{matrixOperations} Zeile 12) durchgef\"uhrt werden soll. \begin{lstlisting}[label=matrixOperations, caption={Zwei Arten von Multiplikationen auf Matrizen.}] >> A = randi(10, [3, 3]) % 2-D Matrix A = 3 8 2 2 10 3 10 7 1 >> B = randi(10, [3, 3]) % dto B = 2 1 7 1 5 9 5 10 5 >> >> A * B % Matrix Multiplikation ans = 24 63 103 29 82 119 32 55 138 >> >> A .* B % Elementweise Multiplikation ans = 6 8 14 2 50 27 50 70 5 >> \end{lstlisting} \section{Boolesche Operationen} Boolesche Ausdr\"ucke sind Anweisungen, die zu \textit{wahr} oder \textit{falsch} ausgewertet werden. Man kennt sie z.B. aus der Mengenlehre. In der Programmierung werdens sie eingesetzt, um z.B. die Beziehung zwischen Entit\"aten zu testen. Hierzu werden die \textit{relationalen Operatoren} (\code{>, <, ==, !}, gr\"o{\ss}er als, kleiner als, gleich und nicht) eingesetzt. Mehrere Ausdr\"ucke werden mittels der \textit{logischen Operatoren} (\code{\&, |}, UND, ODER ) verkn\"upft. Sie sind f\"ur uns 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 folgenden Tabellen zeigen die Wahrheitstabellen f\"ur das logische UND (\ref{logicalandor}, links) aund das logische ODER (\ref{logicalandor}, rechts). 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. \begin{table}[] \caption{Wahrheitstabellen logisches UND (links) und logisches ODER (rechts).}\label{logicalandor} \begin{minipage}[t]{0.4\textwidth} \begin{tabular}{llll} \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ \multicolumn{2}{l}{} & \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} \\ \cline{2-4} & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l|}{\textcolor{red}{falsch}} & \textcolor{red}{falsch} \end{tabular} \end{minipage} \begin{minipage}[t]{0.4\textwidth} \begin{tabular}{llll} \multicolumn{2}{l}{\multirow{2}{*}{}} & \multicolumn{2}{c}{\textbf{B}} \\ \multicolumn{2}{l}{} & \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} \\ \cline{2-4} & \multicolumn{1}{l|}{falsch} & \multicolumn{1}{l|}{\textcolor{mygreen}{wahr}} & \textcolor{red}{falsch} \end{tabular} \end{minipage} \end{table} Anders ist das beim logischen ODER. Hier ist der gesamte Ausdruck wahr, wenn sich der eine \textit{oder} der andere Ausdruck zu wahr auswerten l\"a{\ss}t. Tabelle \ref{logicaloperators} zeigt die logischen Operatoren, die in \matlab{} definiert sind. Zu bemerken sind hier noch die \code{\&\&} und \code{||} 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 ausgewerte wird, dann muss der zweite gar nicht mehr gepr\"uft werden. Die Verwendung der ``short-circuit'' Versionen spart Rechenzeit. Das auschliessende ODER (XOR) ist in \matlab{} nur als Funktion \code{xor(A, B)} verf\"ugbar. \begin{table}[th] \caption{\label{logicaloperators} \textbf{Logische Operatoren in \matlab.}} \begin{center} \begin{tabular}{c|c} \hline \textbf{Operator} & \textbf{Beschreibung} \\ \hline $\sim$ & logisches NOT\\ $\&$ & logisches UND\\ $|$ & logisches ODER\\ $\&\&$ & short-circuit logical UND\\ $\|$ & short-circuit logical ODER\\ \hline \end{tabular} \end{center} \end{table} Um Werte miteinander zu vergleichen gibt es die \textit{relationalen Operatoren} (Tabelle \ref{relationaloperators}). Mit ihnen kann man auf Dinge wie Gleicheit (\code{==}) gr\"o{\ss}er oder kleiner als (\code{>, <}) testen. \begin{table}[th] \caption{\label{relationaloperators} \textbf{Relationale Operatoren in \matlab.}} \begin{center} \begin{tabular}{c|c} \hline \textbf{Operator} & \textbf{Beschreibung} \\ \hline $<$ & kleiner als\\ $>$ & gr\"osser als \\ $==$ & gleich \\ $>=$ & gr\"osser oder gleich \\ $<=$ & kleiner oder gleich \\ $\sim=$ & ungleich\\ \hline \end{tabular} \end{center} \end{table} Das Ergebnis eines Booleschen Ausdrucks ist immer vom Datentyp \textit{logical}. Man kann jede beliebige Variable zu wahr oder falsch auswerten indem man in den Typ \textit{logical} umwandelt. 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 jedoch nur Synonyme f\"ur die \textit{logical} Werte 1 und 0. Man beachte, dass der Zuweisungsoperator \code{=} und der logische Operator \code{==} zwei grundverschiedene Dinge sind. Da sie umgangsprachlich gleich sind kann man sie leider leicht verwechseln. \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 Bollesche Ausdr\"ucke ist das logische Indizieren. Das logische 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 man durch die Verwendung eines Booleschen Ausdrucks auf z.B. einen Vektor einen logischen Vektor gleicher Gr\"o{\ss}e erh\"alt. Dieser wird nun benutzt um auf den urspr\"unglichen Vektor zuzugreifen. \matlab{} gibt nun die Werte an den Stellen zur\"uck, an denen der logische Vektor \textit{wahr} ist (Listing \ref{logicalindexing1}). \begin{lstlisting}[caption={Beispiel Logischen Indizieren.}, label=logicalindexing1] >> x = randn(10, 1); >> % in zwei Schritten >> x_smaller_zero = x < 0; % logischer vektor >> elements_smaller_zero = x(x_smaller_zero); % benutzen, um zuzugreifen >> % oder in einem Schritt >> elements_smaller_zero = x(x < 0); \end{lstlisting} \begin{exercise}{logicalVector.m}{logicalVector.out} Erstelle einen Vektor x mit den Werten 0-10. \begin{enumerate} \item F\"uhre aus: \code{y = x < 5} \item Gib den Inhalt von \code{y} auf dem Bildschirm aus. \item Was ist der Datentyp von \code{y}? \item Gibt alle Elemente aus x zur\"uck, die kleiner als 5 sind. \end{enumerate} Die letzte Zeile kann wie folgt gelesen werden: Gib mir die Elemente von (\code{x}) an den Stellen, an denen \code{x < 5} wahr ist. \end{exercise} \begin{exercise}{logicalIndexingTime.m}{} Angenommen es werden \"uber einen bestimmten Zeitraum Messwerte genommen. Bei solchen Messungen er\"alt man einen Vektor, der die Zeitpunkte der Messung speichert und einen zweiten mit den jeweiligen Messwerten. \begin{itemize} \item Erstelle einen Vektor \code{t= 0:0.001:10;}, der z.B. die Zeit repr\"asentiert. \item Erstelle einen zweiten Vektor \code{x} mit Zufallszahlen der die gleiche L\"ange hat wie \code{t}. Die Werte darin stellen Messungen zu den Zeitpunkten in \code{t} dar. \item Benutze das logische Indizieren um die Messwerte auszuw\"ahlen, die dem zeitlichen Abschnitt 5-6\,s entsprechen. \end{itemize} \begin{figure} \includegraphics[width=0.6\textwidth]{logicalIndexing_time.png} \end{figure} \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 des Programmcodes wiederholt oder nur unter bestimmten Bedingungen ausgef\"uhrt werden. 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 Klonen einzelner Zeilen oder 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 Klonen die entscheidende \"Anderung auch wirklich vorzunehmen. \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 ich einen Fehler gemacht habe, dann muss ich den Fehler in allen Klonen korrigieren (sehr wird dabei der ein oder andere Klon \"ubersehen). \item Verst\"andlichkeit: Solche Abschnitte sind schwerer zu lesen/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. \end{enumerate} Alle Programmiersprachen bieten zur L\"osung dieses Problems die Schleifen. Eine Schleife wird immer dann eingesetzt, wenn man Abschnitte wiederholt ausf\"uhren will. \subsubsection{Die \textbf{for} --- Schleife} Der am h\"aufigsten benutzte Vertreter der Schleifen ist die \textit{for-Schleife}. Sie besteht aus dem \textit{Schleifenkopf} und dem \textit{Schleifenk\"orper}. Der Kopf regelt, wie h\"aufig der Code im K\"orper ausgef\"uhrt wird. \begin{definition} Der Schleifenkopf beginnt mit dem Schl\"usselwort \textbf{for} auf welches folgend die \textit{Laufvariable} definiert wird. In \matlab ``l\"auft''/iteriert eine for-Schleife immer(!) \"uber einen Vektor. Die \textit{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 \textbf{end} beendet. Listing \ref{looplisting} \end{definition} \begin{lstlisting}[caption={Beispiel einer \textbf{for} Schleife. Die Laufvariable \code{x} nimmt mit jeder Iteration der Schleife einen Wert des Vektors \code{1:5} an.}, label=looplisting] for x = 1:5 % ... etwas sinnvolles mit x ... end \end{lstlisting} \begin{exercise}{facultyLoop.m}{facultyLoop.out} Wie k\"onnte Fakult\"at mit einer Schleife implementiert werden? Implementiere eine for Schleife, die die Fakul\"at von einer Zahl \code{n} berechnet. \end{exercise} \subsubsection{Die \textbf{while} --- Schleife} Eine weiterer Schleifentyp, der weniger h\"aufig eingesetzt wird, ist die \textot{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. \begin{definition} Der Schleifenkopf beginnt mit dem Schl\"usselwort \textbf{while} gefolgt von einem \underline{Booleschen Ausdruck}. Solange dieser zu \textit{true} ausgewertet werden kann, wird der Code im Schleifenk\"orper ausgef\"uhrt. Die Schleife wird mit dem Schl\"usselwort \textbf{end} beendet. \end{definition} \begin{lstlisting}[caption={Grundstruktur einer \textbf{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 \textbf{while}-Schleife. \end{exercise} \begin{exercise}{neverendingWhile.m}{} Implementiere eine \textbf{while}-Schleife, die unendlich l\"auft. Tipp: der Boolesche Ausdruck hinter dem \textbf{while} muss immer zu wahr ausgewertet werden. \end{exercise} \subsubsection{Vergleich \textbf{for} und \textbf{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. \item Der K\"orper einer \code{while} Schleife wird nur dann betreten, wenn die Bedinung im Kopf \textbf{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 if --- Anweisung} Am h\"aufigsten genutzter Vertreter ist die \textbf{if} - Anweisung. Sie Wird genutzt um Programmcode nur unter bestimmten Bedingungen auszuf\"uhren. \begin{definition} Der Kopf der if - Anweisung beginnt mit dem Schl\"usselwort \textbf{if} welches von einem \underline{Booleschen Ausdruck} gefolgt wird. Wenn dieser zu \textbf{true} ausgewertet werden kann, wird der Code im K\"orper der Anweisung ausgef\"uhrt. Optional k\"onnen weitere Bedingungen mit dem Schl\"usselwort \textbf{elseif} folgen. Ebenfalls optional ist die Verwendung eines finalen \textbf{else} Falls. Dieser wird immer dann ausgef\"uhrt wenn alle vorherigen Bedingungen nicht erf\"ullt werden. Die \code{if} Anweisung wird mit \textbf{end} beendet. Listing \ref{ifelselisting} zeigt den Aufbau einer if-Anweisung. \end{definition} \begin{lstlisting}[label=ifelselisting, caption={Grundger\"ust einer \textbf{if} Anweisung.}] if x < y % fuehre diesen code aus elseif x > y % etwas anderes soll getan werden else % wenn x == y wieder etwas anderes end \end{lstlisting} \begin{exercise}{ifelse.m}{} Ziehe eine Zufallszahl und \"uberpr\"ufe mit einer geegnet \textbf{if} Anweisung, ob sie: \begin{enumerate} \item ... kleiner als 0.5 ist. \item ... kleiner oder gr\"o{\ss}er-gleich 0.5 ist. \item ... kleiner als 0.5, gr\"o{\ss}er oder gleich 0.5 aber kleiner als 0.75 ist oder gr\"o{\ss}er oder gleich 0.75 ist. \end{enumerate} \end{execise} \subsubsection{Die \code{switch} - Verzweigung} Die \textbf{switch} Verzweigung Wird eingesetzt wenn mehrere F\"alle auftreten k\"onnen, die einer unterschiedlichen Behandlung bed\"urfen. \begin{definition} Wird mit dem Schl\"usselwort \textbf{switch} begonnen, gefolgt von der \textit{switch Anweisung} (Zahl oder String). Jeder Fall auf den die Anweisung \"uberpr\"ft werden soll wird mit dem Schl\"usselwort \textbf{case} eingeleitet. Diese wird gefolgt von der \textit{case Anweisung} welche definiert gegen welchen Fall auf \underline{Gleichheit} getestet wird. F\"ur jeden Fall wird der Programmcode angegeben, der ausgef\"uhrt werden soll Optional k\"onnen mit dem Schl\"usselwort \textbf{otherwise} alle nicht explizit genannten F\"alle behandelt werden. Die \code{switch} Anweisung wird mit \textbf{end} beendet (z.B. in Listing \ref{switchlisting}). \end{definition} \begin{lstlisting}[label=switchlisting, caption={Grundger\"ust einer \textbf{switch} Anweisung.}] mynumber = input('Enter a number:'); switch mynumber case -1 disp('negative eins'); case 1 disp('positive eins'); otherwise disp('etwas anderes'); end \end{lstlisting} Wichtig ist hier, dass in jedem \textbf{case} auf \underline{Gleichheit} der switch-Anweisung und der case-Anweisung getestet wird. \subsubsection{Vergleich if - Anweisung und 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} \section{Skripte und Funktionen} \section{Graphische Darstellung von Daten} %%% Wuerde ich als eigenes Kapitel machen! JB %%% In einem separaten Verzeichnis... \begin{figure} \includegraphics[width=0.9\columnwidth]{convincing} \caption{Die Folgen schlecht annotierter Plots. \url{www.xkcd.com}} \label{xkcdplotting} \end{figure}