Tag 3
Datentypen und Fallunterscheidungen A) Datentypen B) Text-Eingaben und -Ausgaben C) Boolsche Ausdruecke und Fallunterscheidungen D) Hausaufgaben
A) Datentypen
T3_A1) Die wichtigsten Datentypen in Matlab haben Sie bereits kennengelernt: Zahlen, Vektoren und Matrizen. Zahlen sind in Matlab standardmaessig definiert als Fliesskommazahlen mit doppelter Praezision (double). Matrizen und Vektoren sind standardmaessig aus Zahlen vom Typ double zusammengesetzt.
Fliesskommazahlen koennen sehr viele Stellen hinter dem Komma haben, z.B. die Zahl PI. Wenn Sie sich pi anzeigen lassen, sehen Sie nur vier Nachkommastellen. Tatsaechlich rechnet Matlab aber mit sehr viel mehr Stellen. Man kann mit dem Befehl format umstellen wieviele Nachkommastellen gezeigt werden. Probieren Sie aus, wie pi und wie 100*pi angezeigt werden nachdem sie setzen
format long, format long e, format short e, format short
Fuer welche Anwendungen ist welches Format am besten geeignet?
T3_A2) Computer koennen nur einen begrenzten (wenn auch ziemlich grossen) Zahlenbereich darstellen und verarbeiten. Schauen Sie sich die groesste und die kleinste positive Zahl an, mit der Ihr Rechner mit Matlab zuverlaessig rechnen kann: realmax, eps
Was passiert, wenn Sie diesen Bereich ueber- bzw unterschreiten? Probieren Sie z.B. realmax*10, eps/2, realmax+1, 10-eps, 10-eps
T3_A3) Es gibt Bereiche, bei denen gebrochene Werte keinen Sinn ergeben, sondern ausschliesslich ganze Zahlen (integer), z.B. wenn sie ein Element eines Vektors indizieren wollen. Stellen Sie sich vor, Sie haben einen Vektor v, der 100 Datenpunkte einer Messreihe enthaelt und wollen wissen, wie gross Ihr Messergebnis nach 1/3 der Zeit war. Probieren Sie aus:
v=0.1:0.1:10; l=length(v); ind=l/3; m=v(ind)
(Wie sieht die Antwort von Matlab im Vergleich aus, wenn Sie den Messpunkt nach 1/2 der Zeit betrachten wollen?)
Um die Fehlermeldung los zu werden, koennen Sie den Index explizit zu einer Integer-Variable machen:
v=0.1:0.1:10; l=length(v); ind=int16(l/3); m=v(ind)
Eine Alternative dazu ist, weiterhin mit dem Standard-Datentyp double zu arbeiten, aber die entsprechende Zahl zu runden:
v=0.1:0.1:10; l=length(v); ind_a=round(l/3); m_a=v(ind_a)
Allerdings kann man so eine Rundung leicht vergessen, insbesondere wenn mit den Zahlen weiter gerechnet wird. Sicherer ist deshalb, integer zu verwenden, wenn gebrochene Zahlen keinen Sinn machen. Probieren Sie aus:
ind=int16(l/3); m=v(ind); ind2=ind/2; m2=v(ind2) versus
ind_a=round(l/3); m=v(ind_a); ind2_a=ind_a/2; m2_a=v(ind2_a)
Welchen Datentyp hat ind2? Welchen ind2_ a? Was sind ihre Werte?
T3_A4) Ein weiterer wichtiger Datentyp sind Wahrheitswerte (logical). Diese koennen nur zwei Werte annehmen wahr, symbolisiert durch 1, und falsch, symbolisiert durch 0. Logical-Variablen koennen durch den Befehl logical generiert werden, z.B. a=logical(0). Welchen Wert und welchen Typ hat a im Workspace?
Definieren Sie ausserdem b=logical(1). Was passiert bei c=logical(2)?
Den Umgang mit Wahrheitswerten ueben wir heute in Teil C)
T3_A5) Wenn man mit Matlab Texte verarbeiten moechte, werden diese als Zeichenketten (array of char) dargestellt. Die Syntax, wie man eine Zeichenkette generiert und einer Variablen zuweist ist:
text=´Texte werden in Hochkommata eingeschlossen´
Mit solchen Zeichenketten kann man in gleicher Weise arbeiten, wie mit Vektoren, um einzelne Zeichen oder Zeichenfolgen zu indizieren oder Zeichenketten hintereinanderzuhaengen. Leerzeichen zaehlen dabei genauso mit wie alle anderen Zeichen. Probieren Sie aus:
text(1), teil1=text(1:6), teil2=text(17:25), syntax=[teil2 ´ ´ teil1 ´ ´ teil2]
B) Text-Eingaben und -Ausgaben
T3_B1) Wir wissen bereits, dass Berechnungsergebnisse standardmaessig im Command Window ausgegeben werden, ausser sie werden durch ein ";" am Ende der Zeile unterdrueckt.
Es kann jedoch sinnvoll sein, dem Benutzer auch andere Informationen per Textausgabe zur Verfuegung zu stellen. Dies geschieht durch die Funktion disp, der eine Zeichenkette uebergeben wird.
Einfach weil es zu einem Programmierkurs dazugehoert, erzeugen Sie ein Skript hello_world.m das als einzige Zeile enthaelt
disp(´hello world´)
Weil das doch ein wenig langweilig ist, ergaenzen Sie hello_world so, dass es Ihnen ausserdem in freundlicher Art noch das aktuelle Datum verraet, verwenden Sie dafuer die Funktion date.
[datumsanzeige.m]
T3_B2) Mit einer speziellen Art der Textausgabe sind Sie inzwischen bestens vertraut: den rot geschriebenen Fehlermeldungen. Diese koennen Sie auch selber erzeugen durch den Befehl error, z.B. mit error(´so geht es ja nun nicht!´)
Die Funktion error macht jedoch noch mehr als eine rote Textausgabe, sie bricht ausserdem die Ausfuehrung eines Programms ab. Probieren Sie das aus, indem Sie ein den error-Befehl an verschiedenen Stellen eines laengeren Skripts oder Funktion einfuegen (z.B. kompliziert.m von gestern). Wenn Sie in der Datei keine Semikolon verwenden, koennen Sie nachvollziehen, welche Schritte jeweils ausgefuehrt werden.
T3_B3) Wenn man den Benutzer warnen will, dass gerade wahrscheinlich was schief laeuft, aber nicht das ganze Programm abgebrochen werden sollte, gibt es dafuer den Befehl warning. Probieren Sie auch diesen aus.
T3_B4) Man kann Textausgaben auch mit der Ausgabe von Variablenwerten mischen. Der Befehl dafuer ist sprintf. Dieses ist eine Funktion, die als erstes Argument eine Zeichenkette uebergeben bekommt, die ausgegeben werden soll, bei der an Stelle der Variablenwerte die Schluesselbegriffe %g (bei Variablen vom typ double, int, oder logical) oder %s (bei strings) verwendet werden. Als weitere Argumente werden die Variablennamen in der Reihenfolge uebergeben, in der sie im Text auftauchen.
Probieren Sie aus: a=0.2; t='text'; sprintf('jetzt keonnen wir Zahlen wie z.B. %g und auch %s darstellen.',a,t)
Erweitern Sie eins Ihrer Spaghettiskripte oder Funktionen von gestern so, dass die Ausgabe der Laenge mit Angabe der Einheit erfolgt.
(Fuer Leute mit zu viel Zeit oder einem Hang zu schoenen Bildschirmausgaben: mit sprintf kann man die Formatierung sehr exakt festlegen (z.B. Anzahl Nachkommastellen) - wie das geht steht in der Hilfe. Dort gibt es auch Hinweise zum entsprechenden Befehl fprintf, mit dem man formatiert in Dateien schreibt.)
T3_B5) Haeufig moechte man dem Benutzer nicht nur etwas mitteilen, sondern auch Benutzereingaben erhalten. Einen Spezialfall davon haben Sie bereits kennengelernt, den Befehl pause. Wenn es nicht nur entscheidend ist, dass eine Eingabe erfolgt, sondern auch um welche Eingabe es sich handelt, verwendet man den Befehl input. a=input('Eingabe') weist der Variablen a eine Zahl, oder einen Variablenwert zu. Probieren Sie aus:
a=input('Wert fuer a: ') -> bei Abfrage 7 eingeben
b=input('Wert fuer b: ') -> bei Abfrage a eingeben
c=input('Wert fuer c: ') -> bei Abfrage xyz eingeben
Wenn Text eingelesen werden soll, braucht der Befehl als zweiten Eingangswert die Option 's':
c=input('Wert fuer c: ','s') -> bei Abfrage xyz eingeben
d=input('Wert fuer d: ','s') -> bei Abfrage 7 eingeben
e=input('Wert fuer e: ','s') -> bei Abfrage b eingeben
T3_B6) Man kann Zeichenketten in Zahlen umwandeln und umgekehrt. Die Befehle dafuer sind num2str (number to string) und str2num. Probieren Sie aus:
a=1.1, a_char=num2str(a), a_neu=str2num(a)
b='xyz', b_num=str2num(b)
Diese Eigenschaft ist besonders praktisch, um Zeichenketten automatisch zu generieren , z.B. fuer die systematische Benennung von Dateien.
Schreiben Sie ein Programm, dass den Benutzer zuerst nach einer Zeichenkette fragt, dann nach einer Zahl. Speichern Sie die Zeichenkette in einer Datei deren Namen Sie aus 'datei' und der eingegebenen Zahl generieren, z.B. wenn der Benutzer 5 eingegeben hat, nennen Sie die datei 'datei5.mat'.
Achtung, wenn der Dateiname in der Variablen dateiname gespeichert ist, funktioniert save dateiname variablenname nicht. Hierfuer braucht man die kompliziertere (und leider sehr wenig intuitive) Syntax save(dateiname,'variablenname').
T3_B7) Achtung! Matlab hindert Sie nicht daran, mit Zeichenketten zu rechnen! Probieren Sie aus:
a='1', a2=2*a, a2_ok=2*str2num(a),
b='xyz', b+1
T3_B8) Um sich Programmtexte im command window anzeigen zu lassen, gibt es den Befehl type. Probieren Sie in ihrem Arbeitsverzeichnis aus type spaghettiskript. Praktischerweise gilt type nicht nur fuer Ihre eigenen Programme, sondern auch fuer die in Matlab enthaltenen, so dass man sich diese ohne lange Suche ansehen und sich etwas abgucken kann. Probieren Sie z.B. type imagesc (nein, den Programmcode muessen Sie noch nicht verstehen). Bei manchen Kern-Funktionen laesst Matlab sich allerdings nicht auf die Finger schauen, z.B. type sin
C) Boolsche Ausdruecke und Fallunterscheidungen
T3_C1) Kehren wir nochmal zurueck zu unserem Spaghetti-Beispiel: Normalerweise interessiert einen beim Konsum von Mensa-Spaghetti weniger ihre Laenge als eher die Frage "sollte ich die wirklich nehmen?". Auch dabei kann uns Matlab weiterhelfen. Zur Beantwortung dieser Frage brauchen wir zunaechst ein Kriterium. Nehmen wir an, ein besonders hungriger Student geht zur Mensa. Fuer ihn ist das Kriterium zunaechst "Ist die Portion gross genug?", allerdings muessen wir das noch etwas praezisieren: "gross genug" koennte heissen "wiegt die Portion mehr als 300g?". Der Student muss also zunaechst einen Test durchfuehren (die Spaghetti wiegen) und dann sein Verhalten entsprechend davon abhaengig machen. Fuer die Kaufentscheidung des Studenten gilt also der Algorithmus:
Wenn Gewicht>300g:
nimm den Teller
Sonst:
sag dem Thekenpersonal: "ich haette gerne noch einen Nachschlag"
Uebersetzt in Matlab-Syntax sieht das so aus:
if Gewicht>300
disp('Teller nehmen')
else
disp('ich haette gerne noch einen Nachschlag')
end
Schreiben Sie ein Programm, das den Koch nach dem Gewicht der Spaghettiportion fragt und abhaengig von seiner Eingabe entsprechend antwortet.
[hungrigerStudent.m]
T3_C2) Bei der Auswertung der Bedingung in einer if-Abfrage wird intern eine boolsche Variable benutzt. Diese koennen Sie auch explizit anlegen und ansehen:
gross=(Gewicht>300)
if gross
disp('Teller nehmen')
end
T3_ C3) Probieren Sie verschiedene Vergleichsoperatoren aus, indem Sie sich zwei Variablen mit Skalarwerten definieren und diese Vergleichen mit jedem der Vergleichsoperatoren:
<, >, ==, <=, >=, ~=
Wenden Sie die Vergleichsoperatoren auch auf zwei Matrizen gleicher Groesse an. Welchen Typ hat die Ausgabe? Wie sieht die Rechenregel aus?
T3_C4) Vergleichsoperatoren auf Vektoren oder Matrizen anzuwenden, kann sehr hilfreich sein, um in Daten bestimmte Bedingungen zu finden. Laden Sie folgende Messreihe des pH Werts von Aquarienwasser:[phWerte.mat]
Wieviele der Messpunkte sind Messfehler (zumindest wenn Ihre Fische nicht Kiel oben schwimmen)? Wie haeufig wurden zu grosse und wie haeufig zu kleine Werte aufgezeichnet?
[pHWertTest.m]
T3_C5) Ein bisschen Logik: Erzeugen Sie sich Tabellen, in denen alle moeglichen Kombinationen aus Belegungen von zwei Zufallsvariablen verknuepft werden mit:
1. a & b (und)
2. a | b (oder)
3. xor(a,b) (exklusives oder)
4. ~a
[logiktabelle.m]
T3_C6) Mit den Befehlen
E=zeros(7); E(6,3:6)=ones(1,4); E(4,3:5)=ones(1,3); E(2,3:6)=ones(1,4); E(2:6,2)=ones(5,1);
ergibt sich eine Matrix, welche mit der Funktion imagesc(E) einen Buchstaben zeigt. Erzeugen Sie davon durch Anwendung logischer Operatoren ein Negativbild.
T3_C7) Wenn man mehrere Zufallsvariable verknuepft, kann es mehr als zwei Bedingungen geben. Diese werden mit
if (bedingung1)
befehle1
elseif(bedingung2)
befehle2
else
befehle3
end
abgefragt. (Dabei kann es beliebig viele elseif-Teile geben).
Erweitern Sie das Programm aus T3_C1) so, dass der Student die Spaghetti nur kauft, wenn das Gewicht>300g ist und die Dichte>1.05, und dem Koch ansonsten eine der jeweiligen Situation angemessene Antwort gibt. Hierzu brauchen Sie als Schluesselbegriff
elseif Bedingung (steht zwischen if und else, wird ansonsten genause verwendet wie if)
[waehlerischerStudent.m]
T3_C8) Nur fuer Leute mit zu viel Zeit oder gesteigertem Interesse an Programmierkonzepten:
Matlab sieht fuer Abfragen von vielen verschiedenen Faellen eine switch-Anweisung vor. Schauen Sie in der Hilfe nach, wie diese zu verwenden ist und schreiben Sie eine Funktion "arbeitsamt", die einen Namen (string) als Eingabe bekommt und diesen Namen dem zustaendigen Sachbearbeiter zuweist und dessen Namen auf dem Bildschirm ausgibt. Zustaendigkeit fuer Anfangsbuchstaben:
A-D: Frau Schmidt
E-H: Herr Klein
I-L: Frau Gross
M-P: Frau Mueller
Q-T: Herr Maier
U-Z: Herr Dimpfelmoser
D) Hausaufgaben
T3_H1) In folgender Datei sind die Merkmale der Katzen in einem Tierheim gespeichert:
[katzen.mat]. Im Vektor alter ist fuer jede Katze ihr Alter in Jahren gespeichert, im Vektor weibchen ein true, wenn es sich bei der Katze um ein Weibchen handelt, bei Katern ein false. Die Merkmale der Tiere sind jeweils in der gleichen Reihenfolge angeordnet.
Wieviele Katzen sind juenger als 2 Jahre?
Wieviele davon sind Weibchen?
[katzenstatistik.m] [Loesung eines Teilnehmers: katzenstatistik_kurs.m] T3_H2) Bei den Merkmale der Katzen im Tierheim [katzen.mat] findet sich auch eine Matrix farben. Diese besteht aus Wahrheitswerten und ist folgendermassen aufgebaut:
Zeilen: 23 Katzen
Spalte 1: Katze hat schwarzes Fell
Spalte 2: Katze hat rotes Fell
Spalte 3: Katze hat weisses Fell
Spalte 4: Katze hat getigertes Fell Wieviele Katzen haben getigertes Fell?
Wieviele Katzen haben rein getigertes Fell, ohne andere Farben?
Wieviele dreifarbige Glueckskatzen (schwarz-weiss-rot) gibt es?
Wieviele einfarbige Katzen gibt es?
[Loesung eines Teilnehmers: wunschkatze_kurs.m] T3_H4) Man kann den Typ einer Variable im Programmtext testen (was z.B. nuetzlich ist, wenn Benutzer eventuell absoluten Unsinn an eine Funktion uebergeben koennten). Der Test, ob eine Variable einen Wahrheitswert beinhaltet heisst islogical. Finden Sie die anderen Abfragen heraus und schreiben Sie eine Funktion, die fuer eine beliebige Eingabe den Typ der Eingabe auf dem Bildschirm ausgibt.
[variablentyp.m]
T3_H5) Eine extrem wichtige Anwendung von if-Abfragen sind Tests, ob einer Funktion sinnvolle Parameter uebergeben wurden. Ergaenzen Sie Ihre gestern geschriebene spaghettifunktion aus T2_C5 so, dass bei unsinnigen Parameteruebergaben eine Warnung ausgegeben wird.
[spaghettifunktion_mit_Abfragen.m] T3_H6) Erweitern Sie die Funktion diagonale.m vom letzten Kurstag so, dass eine Warnung erfolgt, wenn der Benutzer Eingabeparameter uebergibt, die nicht der Spezifikation entsprechen.
[diagonale_mit_abfrage.m]