stub of the function scripts

This commit is contained in:
Jan Grewe 2015-11-06 16:50:19 +01:00
parent 5b8ff9b59c
commit 86978d4d41
3 changed files with 291 additions and 21 deletions

View File

@ -1,7 +1,7 @@
% create a vector with a random numbers
% create a vector with random numbers
x = rand(1000000, 1);
fprintf('time needed to manually filter elements smaller than 0.5 in a vector of length %i\n', length(x))
fprintf('Time needed to manually filter out elements smaller than 0.5 in a vector of length %i\n', length(x))
tic
results = [];
@ -14,7 +14,7 @@ for i = 1:length(x)
end
toc
fprintf('\ntime needed to do the same with logical indexing\n')
fprintf('\nTime needed to do the same with logical indexing\n')
tic
results = x(x < 0.5);

View File

@ -1,6 +1,6 @@
>> logicalIndexingBenchmark
time needed to manually filter elements smaller than 0.5 in a vector of length 100000
Time needed to manually filter elements smaller than 0.5 in a vector of length 100000
Elapsed time is 0.008562 seconds.
time needed to do the same with logical indexing
Time needed to do the same with logical indexing
Elapsed time is 0.001543 seconds.

View File

@ -6,7 +6,7 @@
\subsection{Variablen}
aEine Variable ist ein Zeiger auf eine Stelle im Speicher. Dieser
Eine 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
@ -758,6 +758,23 @@ nun die Werte an den Stellen zur\"uck, an denen der logische Vektor
von (\code{x}) an den Stellen, an denen \code{x < 5} wahr ist.
\end{exercise}
Logisches Indizieren wurde oben so benutzt, dass die Auswahl auf dem
Inhalt desselben Vektors beruhte. Ein sehr h\"auiger Fall ist
jedoch, dass man die Auswahl aus einem Vektor auf den Inhalt eines
zweiten Vektors basiert. Ein Beispiel ist, dass man \"uber einen
gewissen Zeitraum Daten aufnimmt und aus diesen die Daten eines
bestimmten Zeitraums ausw\"ahlen m\"ochte (Abbildung
\ref{logicalindexingfig}).
\begin{figure}[h]
\includegraphics[width= 0.9\columnwidth]{logicalIndexingTime}
\caption{\texbf{Beispiel f\"ur ``indirektes'' logisches Indizieren.}
Der rot markierte Abschnitt aus den Daten wurde ``indirekt''
anhand logischen Indizierens auf dem Zeitvektor
ausgew\"ahlt.}\label{logicalindexingfig}
\end{figure}
\begin{exercise}{logicalIndexingTime.m}{}
Angenommen es werden \"uber einen bestimmten Zeitraum Messwerte
genommen. Bei solchen Messungen er\"alt man einen Vektor, der die
@ -773,9 +790,6 @@ nun die Werte an den Stellen zur\"uck, an denen der logische Vektor
\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}
@ -898,8 +912,8 @@ end
\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.
l\"auft. Tipp: wenn der Boolesche Ausdruck hinter dem \textbf{while}
zu wahr ausgewertet wird, wird die Schleife weiter ausgef\"uhrt.
\end{exercise}
@ -988,11 +1002,11 @@ auftreten k\"onnen, die einer unterschiedlichen Behandlung bed\"urfen.
mynumber = input('Enter a number:');
switch mynumber
case -1
disp('negative eins');
disp('negative one');
case 1
disp('positive eins');
disp('positive one');
otherwise
disp('etwas anderes');
disp('something else');
end
\end{lstlisting}
@ -1012,15 +1026,271 @@ switch-Anweisung und der case-Anweisung getestet wird.
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 \textbf{break} und
\textbf{continue} eingesetzt (Listing \ref{breakcontinuelisting}
zeigt, wie sie eingesetzt werden k\"onnen).
\begin{lstlisting}[caption={Ensatz der \code{continue} und \code{break} Schl\"usselworte um die Ausf\"uhrung von Abschnitte in Schleife zu \"uberspringen oder abzubrechen.}, label=breakcontinuelisting]
for x = 1:10
if(x > 2 & x < 5)
continue;
end
disp(x);
end
x = 1;
while true
if(x > 5)
break;
end
disp(x);
x = x + 1
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.
\begin{enumerate}
\item Benutze eine \code{for} Schleife um die Element 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?}
\section{Graphische Darstellung von Daten}
%%% Wuerde ich als eigenes Kapitel machen! JB
%%% In einem separaten Verzeichnis...
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\"r Zeile von oben nach unten ausgef\"uhrt.
\matlab{} kennt drei Arten von Programmen:
\begin{enumerate}
\item Skripte
\item Funktionen
\item Objekte (werden wir ignorieren)
\end{enumerate}
Alle Programme werden in den sogenannten \textit{m-files} gespeichert
(z.B. \textit{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 erzuegt wurde im
\textit{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 \textbf{Funktionen}.
\subsection{Funktionen}
Eine Funktion in \matlab{} wird \"ahnlich zu einer mathematischen
Funktion definiert:
\[ y = f(x) \]
Die Funktion hat einen Namen $f$, sie h\"angt von einem Argument $x$
ab und liefert ein Ergebnis $y$ zur\"uck. Listing
\ref{functiondefinitionlisting} zeigt wie das in \matlab{} umgesetzt
wird.
\begin{lstlisting}[caption={Funktionsdefinition in \matlab{}}, label=functiondefinitionlisting]
function [y] = function_name(arg_1, arg_2)
% ^ ^ ^
% Rueckgabewert Argument_1, Argument_2
\end{lstlisting}
Ein Funktion beginnt mit dem Schl\"usselwort \textbf{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 mit einem \textbf{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 \textbf{nicht} sichtbar.
\item Variablen, die in der Funktion definiert werden erscheinen
\textbf{nicht} im Workspace.
\end{itemize}
\item Erhöht 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={Eine Beispielfunktion, die eine Reihe Sinus plottet.},label=badsinewavelisting]
function meine_erste_funktion() % 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{lstlisting}
Dieses schlechte 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 gut.
\item Was sie tut, ist festgelegt und kann von au{\ss}en nicht
beeinflusst werden.
\item Sie tut drei Dinge aus einmal: Sinus berechnen \textbf{und}
Amplituden \"andern \textbf{und} graphisch darstellen.
\item Es ist nicht (einfach) m\"oglich an die berechneten Daten zu
kommen.
\item Keinerlei Dokumentation. Man muss den code lesen um zu
rekonstruieren, was sie tut.
\end{itemize}
Bevor wir anfangen die Funktion zu verbessern sollten wir uns Gedanken
\"uber das zu l\"osende Problem zu machen:
\begin{enumerate}
\item Welches Problem soll gel\"ost werden?
\item Aufteilen in Teilprobleme.
\item Gute Namen finden.
\item Definieren der Schnittstellen --- Was muss die Funktion
wissen? Was möchte ich von ihr haben?
\item Daten zur\"uck geben (R\"uckgabewerte definieren).
\end{enumerate}
Das Beispiel aus Listing \ref{badsinewavelisting} kann in drei
Teilprobleme aufgetrennt werden:
\begin{enumerate}
\item Berechnen der \textbf{einzelnen} Sinus.
\item Plotten der Daten.
\item Koordinieren von Berechung und Darstellung mit
unterschiedlichen Amplituden.
\end{enumerate}
\begin{lstlisting}
function [t, y] = calculate_sinewave(frequency, amplitude, t_max, t_step)
x = (0:t_step:t_max);
y = sin(frequency * t * 2 * pi) * amplitude;
end
\end{lstlisting}
\textbf{2. Plotten einer einzelnen Schwingung:}
\begin{enumerate}
\item Namen finden
\item Schnittstelle definieren: Was will ich von der Funktion?
Welche Information muss ich ihr geben?\pause
\begin{itemize}
\item Funktion muss wissen: Welche Daten soll sie plotten? Zeitachse,
y-Werte, einen Namen f\"ur die Legende?
\item Muss nichts zur\"uckgeben.
\end{itemize}
\end{enumerate}
\begin{lstlisting}
function plot_sinewave(x_data, y_data, name)
plot(x_data, y_data, 'displayname', name)
end
\end{lstlisting}
\textbf{3. Erstellen eines \textbf{Skriptes} zur Koordinierung:}
\begin{enumerate}
\item Namen finden
\item Definieren eins Vektors, f\"ur die Amplituden.
\item Definieren einer Variable f\"ur die Frequenz.
\item Definieren der Variablen f\"ur das Maximum und die
Schrittweite der x-Achse.
\item \"Offnen einer neuen Abbildung (\code{figure()}).
\item Setzen des \code{hold on}.
\item \code{for}-Schleife, die über die Amplituden iteriert, die
Sinus berechnen l\"asst und die Resultate an die Plot-Funktion
weiterreicht.
\end{enumerate}
Skript: \verb+plot_sinewaves.m+
\begin{lstlisting}
amplitudes = 0.25:0.25:1.25;
frequency = 2;
t_max = 10;
t_step = 0.01;
figure()
hold on
for a = amplitudes
name = num2str(a);
[x_data, y_data] = calculate_sinewave(frequency, a, t_max, t_step);
plot_sinewave(x_data, y_data, name)
end
legend('show')
\end{lstlisting}
\begin{exercise}{}{}
Erweitert das Programm so, dass auch ein Satz von Frequenzen benutzt
wird.
\end{exercise}
\subsection{Fazit}
Funktionen sind kleine Code Fragmente, die
\begin{enumerate}
\item ... genau eine Aufgabe erledigen.
\item ... Argumente entgegennehmen k\"onnen.
\item ... R\"uckgabewerte haben k\"onnen.
\item ... ihren eigenen G\"ultigkeitsbereich haben.
\item ... Skripten fast immer vorzuziehen sind.
\end{enumerate}
Die vorangegangene Diskussion klingt, alsob Skripte zu verteufeln und
zu vermeiden w\"aren. Dem ist nicht so. In Wahrheit sind sie daf''ur
gemacht, Hand in Hand ein Probelm zu l\"osen. W\"ahrend die Funktionen
relativ kleine ``verdauliche'' Teilprobleme l\"osen. Sind die Skripte
daf\"ur gemacht den Rahmen zu bilden und den Ablauf zu koordinieren.
Ein m\"ogliches Programmlayout k\"onnte so aussehen:
\begin{figure}
\includegraphics[width=0.9\columnwidth]{convincing}
\caption{Die Folgen schlecht annotierter
Plots. \url{www.xkcd.com}} \label{xkcdplotting}
\includegraphics[width=0.5\columnwidth]{./images/simple_program.pdf}
\end{figure}