Merge branch 'master' of whale.am28.uni-tuebingen.de:scientificComputing

This commit is contained in:
Jan Grewe 2016-10-18 21:54:43 +02:00
commit 6c210a8901
4 changed files with 336 additions and 289 deletions

View File

@ -22,6 +22,9 @@
plots haben, die wir machen!
\item subplot
\item Uebersicht zu wichtigen plot Befehlen (plot, scatter, bar, step, ...)
\item Funktionenplotten (siehe auch Design patterns) und untersampleter Sinus
\item Verschiedene Stile fuer Achsenbeschriftung (gross/kleinschreibungen, Kalmmertyp fuer Einheiten), stay with one style!
\item Stay with a coherent style (font type/style/size, colors schemes, line styles/thickness, point styles)
\end{itemize}
\end{document}

View File

@ -198,7 +198,7 @@ voneinander ausf\"uhrbar sein. Das Skript sollte nach dem Muster:
\part Einer dritte Variable \code{c} soll der Wert \code{a+1e-16}
zugewiesen werden. Was ist das Ergebnis von \code{c-a} ? Warum?
\begin{solution}
Das Ergebnis ist 0! Auch die doble Werte haben nur eine endliche
Das Ergebnis ist 0! Auch die double Werte haben nur eine endliche
P\"azision in den Nachkommastellen.
\end{solution}
\part Berechne \verb=(2^52 + 1) - 2^52= sowie

View File

@ -29,6 +29,10 @@
\item Doppelte for-Schleife
\item File output and input (load, save, fprintf, scanf) (extra chapter?)
\item help() und doc()
\item A box about sampling of contiunous data.
\item A box about foo and bar?
\item function arguments, order does matter, names do as well.
\item function return values. order does not matter, names do
\end{itemize}
\end{document}

View File

@ -15,7 +15,7 @@ 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
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.
@ -261,7 +261,7 @@ c =
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
yet more powerful way (listing~\ref{vectorsizeslisting}). The above
used vector \varcode{a} has the following size:
\begin{lstlisting}[label=vectorsizeslisting, caption={Size of a vector.}]
@ -937,9 +937,10 @@ The basic concept is that applying a Boolean operation on a vector
results in a \code{logical} vector of the same size (see
listing~\ref{booleanexpressions}. This logical vector is then used to
select only those values for which the logical vector is true. Line 14
in listing~\ref{logicalindexing} can be read: ``Give me all those
in listing~\ref{logicalindexing1} can be read: ``Select all those
elements of \varcode{x} where the Boolean expression \varcode{x < 0}
evaluates to true''.
evaluates to true and store the result in the variable
\emph{x\_smaller\_zero}''.
\begin{lstlisting}[caption={Logical indexing.}, label=logicalindexing1]
>> x = randn(1, 6) % a vector with 6 random numbers
@ -1019,7 +1020,9 @@ major classes of such statements:
\end{enumerate}
\subsection{Loops}
As the name already suggests loops are used to execute the same parts of the code repeatedly. In one of the earlier exercises the faculty of five has been calculated as depicted in listing~\ref{facultylisting}.
As the name already suggests loops are used to execute the same parts
of the code repeatedly. In one of the earlier exercises the faculty of
five has been calculated as depicted in listing~\ref{facultylisting}.
\begin{lstlisting}[caption={Calculation of the faculty of 5 in five steps}, label=facultylisting]
>> x = 1;
@ -1089,115 +1092,112 @@ purpose. The \code{for} loop is closed with the keyword
\subsubsection{The \varcode{while} --- loop}
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 ...
The \code{while}--loop is the second type of loop that is available in
almost all programming languages. Other, than the \code{for} -- loop,
that iterates with the running variable over a vector, the while loop
uses a Boolean expression to determine when to execute the code in
it's body. The head of the loop starts with the keyword \code{while}
that is followed by a Boolean expression. If this can be evaluated to
true, the code in the body is executed. The loop is closed with an
\code{end}.
\begin{lstlisting}[caption={Basic structure of a \code{while} loop.}, label=whileloop]
while x == true % head with a Boolean expression
% execute this code if the expression yields true
end
\end{lstlisting}
\begin{exercise}{facultyWhileLoop.m}{}
Implementiere die Fakult\"at mit einer \code{while}-Schleife.
Implement the faculty of a number \varcode{n} using a \code{while}
-- loop.
\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.
Implement a \code{while}--loop that is never-ending. Hint: the body
is executed as long as the Boolean expression in the head is
true. You can escape the loop by pressing \keycode{Ctrl+C}.
\end{exercise}
\subsubsection{Vergleich \varcode{for} -- und \varcode{while}--Schleife}
\subsubsection{Comparison \varcode{for} -- and \varcode{while} -- loop}
\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.
\item Both execute the code in the body iterative.
\item When using a \code{for} -- loop the body of the loop is executed
at least once (except when the vector used in the head is empty).
\item In a \code{while} -- loop, the body is not necessarily
executed. It is entered only if the Boolean expression in the head
yields true.
\item The \code{for} -- loop is best suited for cases in which the
elements of a vector have to be used for a computation or when the
number of iterations is known.
\item The \code{while} -- loop is best suited for cases when it is not
known in advance how often a certain piece of code has to be
executed.
\item Any problem that can be solved with one type can also be solve
with the other type of loop.
\end{itemize}
\subsection{Bedingte Anweisungen und Verzweigungen}
\subsection{Conditional expressions}
Bedingte Anweisungen und Verzweigungen sind Kontrollstrukturen, die
regeln, dass der in ihnen eingeschlossene Programmcode nur unter
bestimmten Bedingungen ausgef\"uhrt wird.
The conditional expression are used to control that the enclosed code
is only executed under a certain condition.
\subsubsection{Die \varcode{if} -- Anweisung}
\subsubsection{The \varcode{if} -- statement}
Am h\"aufigsten genutzter Vertreter ist die \code{if} -
Anweisung. Sie wird genutzt um Programmcode nur unter bestimmten
Bedingungen auszuf\"uhren.
The most prominent representative of the conditional expressions is
the \code{it} statement (sometimes also called \code{if - else}
statement). It constitutes a kind of branching point. It allows to
control which code is executed.
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.
Again, the statement consists of the head and the body. The head
begins with the keyword \code{if} followed by a Boolean expression
that controls whether or not the body is entered. Optionally the body
can be either ended by the \code{end} keyword or followed by
additional statements \code{elseif}, which allows to add another
Boolean expression and to catch a certain condition or the \code{else}
the provide a default case. The last body of the \code{if - elseif -
else} statement has to be finished with the \code{end}
(listing~\ref{ifelselisting}).
\begin{lstlisting}[label=ifelselisting, caption={Grundger\"ust einer \varcode{if} Anweisung.}]
if x < y
% fuehre diesen code aus wenn x < y
\begin{lstlisting}[label=ifelselisting, caption={Structure of an \code{if} statement.}]
if x < y % head
% body I, executed only if x < y
elseif x > y
% etwas anderes soll getan werden fuer x > y
% body II, executed only if the first condition did not match and x > y
else
% wenn x == y, wieder etwas anderes
% body III, executed only if the previous conditions did not match
end
\end{lstlisting}
\begin{exercise}{ifelse.m}{}
Ziehe eine Zufallszahl und \"uberpr\"ufe mit einer geeigneten \code{if} Anweisung, ob sie
Draw a random number and check with an appropriate \code{if}
statement whether it is
\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.
\item less than 0.5.
\item less or greater-or-equal 0.5.
\item (i) less than 0.5, (ii) greater-or-equal 0.5 but less than
0.75 or (iii) greater-or-equal to 0.75.
\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.
\subsubsection{The \varcode{switch} -- statement}
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}).
The \code{switch} statement is used whenever a set of conditions
requires separate treatment. The statement is initialized with the
\code{switch} keyword that is followed by \emph{switch expression} (a
number or string). It is followed by a set of \emph{case expressions}
which start with the keyword \code{case} followed by the condition
that defines against which the \emph{switch expression} is tested. It
is important to note that the case expression always checks for
equality! Optional the case expressions may be followed by the keyword
\code{otherwise} which catches all cases that were not explicitly
stated above (listing~\ref{switchlisting}).
\begin{lstlisting}[label=switchlisting, caption={Grundger\"ust einer \varcode{switch} Anweisung.}]
\begin{lstlisting}[label=switchlisting, caption={Structure of a \varcode{switch} statement.}]
mynumber = input('Enter a number:');
switch mynumber
case -1
@ -1209,31 +1209,29 @@ switch mynumber
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}
\subsubsection{Comparison \varcode{if} and \varcode{switch} -- statements}
\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.
\item Using the \code{if} statement one can test for arbitrary cases
and treat them separately.
\item The \code{switch} statement does something similar but is always
checks for the equality of \emph{switch} and \emph{case}
expressions.
\item The \code{switch} is a little bit more compact and nicer to read
if many different cases have to be handled.
\item The \code{switch} is used less often and can always be replaced
by an \code{if} statement.
\end{itemize}
\subsection{Die Schl\"usselworte \code{break} und \code{continue}}
\subsection{The keywords \code{break} and \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).
Whenever the execution of a loop should be ended or if you want to
skip the execution of the body under certain circumstances, one can
use the keywords \code{break} and \code{continue}
(listings~\ref{continuelisting} and \ref{continuelisting}).
\begin{lstlisting}[caption={Abbrechen von Schleifen mit \varcode{break}.}, label=breaklisting]
\begin{lstlisting}[caption={Stop the execution of a loop using \varcode{break}.}, label=breaklisting]
>> x = 1;
while true
if (x > 3)
@ -1248,7 +1246,7 @@ und \ref{continuelisting} zeigen, wie sie eingesetzt werden k\"onnen).
3
\end{lstlisting}
\begin{lstlisting}[caption={\"Uberspringen von Code-Abschnitten in Schleifen mit \varcode{continue}.}, label=continuelisting]
\begin{lstlisting}[caption={Skipping iterations using \varcode{continue}.}, label=continuelisting]
for x = 1:5
if(x > 2 & x < 5)
continue;
@ -1262,176 +1260,184 @@ end
\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.
Above we claimed the logical indexing is faster and much more
convenient than the manual selection of elements of a vector. By now
we have all the tools at hand to test this. \\
For this test create a large vector with 100000 (or more) random
numbers. Filter from this vector all numbers that are less than 0.5
and copy them to a second vector. Surround you code with the brother
\code{tic} and \code{toc} to have \matlab{} measure the time that
has passed between the calls of \code{tic} and \code{toc}.
\begin{enumerate}
\item Benutze eine \code{for} Schleife um die Elemente auszuw\"ahlen.
\item Benutze logisches Indizieren.
\item Use a \code{for} loop to select the matching values.
\item Use logical indexing.
\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.
Implement a 1-D random walk: Starting from the initial position $0$
the agent takes a step in a random direction.
\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.
\item The program should do 10 random walks with 1000 steps each.
\item With each step decide randomly whether the position is changed
by $+1$ or $-1$.
\item Store all positions.
\item Create a figure in which you plot the position as a function
of the steps.
\end{itemize}
\end{exercise}
\section{Skripte und Funktionen}
\section{Scripts and functions}
\subsection{Was ist ein Programm?}
\subsection{What is a program?}
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.
A program is little more than a collection of statement stored in a
file on the computer. When it is \emph{called}, it is brought to life
and executed line-by-line from top to bottom.
\matlab{} kennt drei Arten von Programmen:
\matlab{} knows three types of programs:
\begin{enumerate}
\item \codeterm[Skript]{Skripte}
\item \codeterm[Funktion]{Funktionen}
\item \codeterm[Objekt]{Objekte} (werden wir hier nicht behandeln)
\item \codeterm[Script]{Scripts}
\item \codeterm[Function]{Functions}
\item \codeterm[Object]{Objects} (not covered here)
\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]
Programs are stored in so called \codeterm{m-files}
(e.g. \file{myProgram.m}). To use them they have to be \emph{called}
from the command line of within another program. Storing your code in
programs increases the re-usability. So far we have used
\emph{scripts} to store the solutions of the exercises. Any variable
that was created appeared in the \codeterm{workspace} and existed even
after the program was finished. This is very convenient but also bears
some risks. Consider the case that \file{script\_a.m} creates a
certain variable and assigns a value to it for later use. Now it calls
a second program (\file{script\_b.m}) that, by accident, uses the same
variable name and assigns a different value to it. When
\file{script\_b.m} is done, the control returns to \file{script\_a.m}
and if it now wants to read the previously stored variable, it will
contain a different value than expected. Bugs like this are hard to
find since each of the programs alone is perfectly fine and works as
intended. A solution for this problem are the
\codeterm[Function]{functions}.
\subsection{Functions}
Functions in \matlab{} are similar to mathematical functions
\[ y = f(x) \] Here, the mathematical function has the name $f$ and it
has one \codeterm{argument} $x$ that is transformed into the
function's output value $y$. In \matlab{} the syntax of a function
declaration is very similar (listing~\ref{functiondefinitionlisting}).
\begin{lstlisting}[caption={Declaration of a function in \matlab{}}, label=functiondefinitionlisting]
function [y] = functionName(arg_1, arg_2)
% ^ ^ ^
% Rueckgabewert Argument_1, Argument_2
% return value 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:
The keyword \code{function} is followed by the return value(s) (it can
be a list \code{[]} of values), the function name and the
argument(s). The function head is then followed by the function's
body. A function is ended by and \code{end} (this is in fact optional
but we will stick to this). Each function that should be directly used
by the user (or called from other programs) should reside in an
individual \code{m-file} that has the same name as the function. By
using functions instead of scripts we gain several advantages:
\begin{itemize}
\item Kapseln von Programmcode, der f\"ur sich eine Aufgabe l\"ost.
\item Definierte Schnittstelle.
\item Eigener G\"ultigkeitsbereich:
\item Encapsulation of program code that solves a certain task. It can
be easily re-used in other programs.
\item There is a clear definition of the function's interface. What
does the function need (the arguments) and what does it return (the
return values).
\item Separated scope:
\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.
\item Variables that are defined within the function do not appear
in the workspace and cannot cause any harm there.
\item Variables that are defined in the workspace are not visible to
the function.
\end{itemize}
\item Erh\"oht die Wiederverwendbarkeit von Programmcode.
\item Erh\"oht die Lesbarkeit von Programmen, da sie
\"ubersichtlicher werden.
\item Functions increase re-usability.
\item Increase the legibility of programs since they are more clearly
arranged.
\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);
The following listing (\ref{badsinewavelisting}) shows a function that
calculates and displays a bunch of sine waves with different amplitudes.
\begin{lstlisting}[caption={Bad example of a function that displays a series of sine waves.},label=badsinewavelisting]
function meineFirstFunction() % function head
t = (0:0.01:2);
frequency = 1.0;
amplitudes = [0.25 0.5 0.75 1.0 1.25];
for i = 1:length(amplitudes)
y = sin(frequency * 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:
\code{myFirstFunction} (listing~\ref{badsinewavelisting}) is a
prime-example of a bad function. There are several issues with it's
design:
\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.
\item The function's name does not tell anything about it's purpose.
\item The function is made for exactly one use-case (frequency of
1\,Hz and five amplitudes).
\item The function's behavior is \enterm{hard-coded} within it's body
and cannot be influenced without changing the function itself.
\item It solves three tasks at the same time: calculate sine
\emph{and} change the amplitude \emph{and} plot the result.
\item There is no way to access the calculated data.
\item No documentation. One has to read and understand the code to
learn what is does.
\end{itemize}
Bevor wir anfangen die Funktion zu verbessern mu{\ss} definiert werden
was das zu l\"osende Problem ist:
Before we can try to improve the function the task should be clearly
defined:
\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).
\item Which problem should be solved?
\item Can the problem be subdivided into smaller tasks?
\item Find good names for each task.
\item Define the interface. Which information is necessary to solve
each task and which results should be returned to the caller
(e.g. the user of another program that calls a function)?
\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}
As indicated above the \code{myFirstFunction} does three things at
once, it seems natural, that the task should be split up into three
parts. (i) Calculation of the individual sine waves defined by the
frequency and the amplitudes (ii) graphical display of the data and
(iii) coordination of calculation and display.
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.
\paragraph{I. Calculation of a single sine wave}
Before we start coding it is best to again think about the task and
define (i) how to name the function, (ii) which information it needs
(arguments), and (iii) what it should return to the caller.
\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}
\item \codeterm[Function!Name]{Name}: the name should be descriptive
of the function's purpose, i.e. the calculation of a sine wave. A
appropriate name might be \code{sinewave()}.
\item \codeterm[Function!Arguments]{Arguments}: What information does
the function need to do the calculation? There are obviously the
frequency as well as the amplitude. Further we may want to be able
to define the duration of the sine wave and the temporal
resolution. We thus need four arguments which should also named to
describe their content: \code{amplitude, frequency, t\_max,} and
\code{t\_step} might be good names.
\item \codeterm[Function!Return values]{Return values}: For a correct
display of the data we need two vectors. The time, and the sine wave
itself. We just need two return values: \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]
Having defined this we can start coding
(listing~\ref{sinefunctionlisting}).
\begin{lstlisting}[caption={Function that calculates a sine wave.}, label=sinefunctionlisting]
function [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
% Calculate a sinewave of a given frequency, amplitude,
% duration and temporal resolution.
@ -1447,23 +1453,36 @@ function [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
% 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;
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}).
\paragraph{II. Plotting a single sine wave}
The display of the sine waves can also be delegated to a function. We
can now decide whether we want the function to plot all sine waves at
once, or if we want design a function that plots a single sine wave
and that we then call repeatedly for each frequency/amplitude
combination. The most flexible approach is the latter and we will
thus implement it this way. We might come up with the following
specification of the function:
\begin{enumerate}
\item It should plot a single sine wave. But it is not limited to sine
waves. It's name is thus: \code{plotFunction()}.
\item What information does it need to solve the task? The
to-be-plotted data as there is the values \code{y\_data} and the
corresponding \code{x\_data}. As we want to plot series of sine
waves we might want to have a \code{name} for each function to be
displayed in the figure legend.
\item Are there any return values? No, this function is just made for
plotting, we do not need to return anything.
\end{enumerate}
With this specification we can start to implement the function
(listing~\ref{sineplotfunctionlisting}).
\begin{lstlisting}[caption={Funktion zur graphischen Darstellung der Daten.}, label=sineplotfunctionlisting]
\begin{lstlisting}[caption={Function for the graphical display of data.}, label=sineplotfunctionlisting]
function plotFunction(x_data, y_data, name)
% Plots x-data against y-data and sets the display name.
%
@ -1478,31 +1497,41 @@ 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]
\paragraph{III. One script to rule them all}
The last task is to write a script to control the calculations and the
plotting of the sine waves. Classically, such controlling of sub-tasks
is handled in a script. It could be done with a function but if
there is a reason for the existence of scripts then it is this.
Again, we need to specify what needs to be done:
\begin{enumerate}
\item The task is to display multiple sine waves. We want to have a
fixed frequency but there should be various amplitudes displayed. An
appropriate name for the script (that is the name of the m-file)
might be \file{plotMultipleSinewaves.m}.
\item What information do we need? we need to define the
\code{frequency}, the range of \code{amplitudes}, the
\code{duration} of the sine waves, and the temporal resolution given
as the time between to points in time, i.e. the \code{stepsize}.
\item We then need to create an empty figure, and work through the
rang of \code{amplitudes}. We must not forget to switch \code{hold
on} if we want to see all the sine waves in one plot.
\end{enumerate}
The implementation is shown in listing~\ref{sinesskriptlisting}.
\begin{lstlisting}[caption={Control script for the plotting of sine waves.},label=sinesskriptlisting]
amplitudes = 0.25:0.25:1.25;
frequency = 2.0;
t_max = 10.0;
t_step = 0.01;
duration = 10.0; % seconds
stepsize = 0.01; % seconds
figure()
hold on
for i = 1:length(amplitudes)
[x_data, y_data] = sinewave(frequency, amplitudes(i), ...
t_max, t_step);
duration, stepsize);
plotFunction(x_data, y_data, sprintf('freq: %5.2f, ampl: %5.2f',...
frequency, amplitudes(i)))
end
@ -1511,34 +1540,45 @@ legend('show')
\end{lstlisting}
\begin{exercise}{plotMultipleSinewaves.m}{}
Erweiter das Programm so, dass die Sinusse f\"ur einen Satz von
Frequenzen geplottet wird.
Extend the program to plot also a range of frequencies.
\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}
\begin{ibox}[t]{\label{whenscriptsbox}When to use scripts and functions}
It is easily possible to solve any programming problem only with
functions. Avoiding functions is also possible but ends very messy
and extremely hard to debug when the project grows. The effort for
avoiding naming conflicts or cleaning up the workspace increases
with the size of the project. Generally, functions should be
preferred over scripts in almost all cases. There are, however,
situations when a script offers advantages.
\begin{minipage}{0.5\textwidth}
\includegraphics[width=0.9\columnwidth]{simple_program}
\end{minipage}
\begin{minipage}{0.5\textwidth}
\textbf{Controlling a task.} Solving tasks that involve calling
sub-routines, as we did above, is one of these situations (see
figure). The script calls functions and takes care of passing the
correct arguments and storing the return values. \linebreak
\textbf{Interactive development.} During the development phase a
script grows as one \emph{interactively} works on the command
line. Commands that have been tested are then transferred to the
script.
\end{minipage}\vspace{0.25cm}
Interactive programming is one of the main strengths of
\matlab{}. Interactive refers to the interaction between the
commands executed on the command line and the variables stored in
the workspace. The immediate feedback if a certain operation works
on the data stored in a variable or if the returned results are
correct speeds up the developmental progress.
\textbf{Special solutions.} Program code that is only valid one very
specific problem may reside in a script. As soon as there is code
duplication or it grows too large, it is high time to consider
extracting features into separate functions.
\end{ibox}