matlab — eine einführung - WWW-Docs for TU

Werbung
MATLAB — E INE E INFÜHRUNG
basierend auf den Skripten von
• Prof. Dr. Martin Reißel, Fachhochschule Aachen, Standort Jülich
• M.Sc. Ivan Cherlenyak und Prof. Dr. Hans-Jürgen Reinhardt, Universität Siegen
• Dr. Susanne Teschl, Fachhochschule Technikum Wien
• Prof. Dr. Jörn Behrens und Prof. Dr. Armin Iske, Alfred Wegener Institute für Polarund Meeresforschung sowie Universität Hamburg
Kapitel 1
Was ist MATLAB
Kurz gesagt: MATLAB ist ein Softwarepaket für numerische Berechnungen und für die
Visualisierung von Daten im technisch-wissenschaftlichen Bereich. MATLAB wurde in
den 70er Jahren an der University of New Mexico und der Stanford University entwickelt
um Kurse aus Lineare Algebra und Numerische Analysis zu unterstützen. Der Name
(MATrix LABoratory) erinnert noch daran. Heute ist MATLAB ein universelles Werkzeug, das in weiten Bereichen der angewandten Mathematik eingesetzt wird.
Man kann MATLAB auf zwei Arten verwenden:
• Bei der interaktiven Verwendung werden Anweisungen direkt über die Tastatur eingegeben und sofort ausgeführt.
• Für umfangreiche Probleme ist es empfehlenswert, MATLAB als Programmiersprache einzusetzen.
Wesentlichen Eigenschaften sind:
• die Sprache wird interpretiert, d.h. Übersetzen etc. entfällt
• grundlegender Datentyp sind doppeltgenaue Matrizen; Variablen (auch Felder) müssen nicht vereinbart werden
• vom Benutzer definierte Funktionen und Unterprogramme werden einfach in Textdateien (m-Files) abgespeichert und können dann wie eingebaute Funktionen benutzt werden
2
3
• auf dieser Basis gibt es zahlreiche Erweiterungen (Toolboxes), die (nach Kauf) eine
Unmenge an Funktionalitäten zur Verfügung stellen
• ein einfaches Hilfe-System, in dem auch Dokumentationen eigener Funktionen
leicht handhabbar sind.
Darüber hinaus können auch C- und Fortran-Programme in Form von sogenannten mexFiles von MATLAB ausgeführt werden.
Nach dem Hochfahren von MATLAB sollte etwa folgendes Fenster zu sehen sein
Abbildung 1.1: Matlab Oberfläche.
Das Fenster ist in 5 Bereiche geteilt:
• in der Mitte befindet sich das Kommandofenster, in dem der Benutzer seine Befehle
eingibt und auch Ausgaben des Programms angezeigt werden
4
• rechts oben werden (bei Einstellung Workspace) alle augenblicklich vorhandenen
Variablen mit Typ und Speicherbedarf angezeigt
• rechts unten werden (bei Einstellung Command History) alle vom Benutzer eingegebenen Kommandos angezeigt
• links oben sind (bei Einstellung Current Directory) alle vom Benutzer in seinem
Arbeitsverzeichnis abgelegten m-Files zu sehen
• links unten werden Details zu der gewählten Datei angezeigt, z.B. Name der Funktion.
Für jedes neue Projekt sollte ein eigenes Verzeichnis angelegt werden. Damit MATLAB in
diesem Verzeichnis arbeitet, muss am oberen Rand des Fensters unter “Current Directory“
das jeweilige Verzeichnis eingestellt werden.
Abbildung 1.2: Aktuelles Verzeichnis.
1.1
Hilfe
MATLAB verfügt über umfangreiche Online-Hilfen. Mit diesen erhalten Sie detaillierte
Informationen zur Funktionalität von MATLAB. Die Hilfsysteme können mit den Befehlen help, helpwin und helpdesk aufgerufen werden.
• Das help- Kommando.
>> help name
gibt Hilfetext zur Variable oder Funktion “name“ aus. Alle MATLAB-Funktionen
sind in logische Gruppen (Themen) eingeteilt, und die MATLAB-Verzeichnisstruktur
basiert auf dieser Einteilung. Gibt man alleine “help“ ein, so wird diese Gruppierung angezeigt. Hiermit kann man sich nun weiter vortasten.
5
• Das lookfor- Kommando
Basierend auf einem Schlüsselwort können Sie mit dem lookfor-Kommando nach
Funktionen suchen. Dabei wird die erste Zeile des help-Textes jeder MATLABFunktion ausgegeben, die das angegebene Schlüsselwort beinhaltet. Sucht man zum
Beispiel Informationen über Splines, dann gibt man am Prompt
>> lookfor spline
an.
• Das Hilfefenstersystem helpwin
Gibt man den Befehl
>> helpwin
ein, so wird ein neues Windowsfenster geöffnet (siehe Abbildung 1.3), das verwendet werden kann, um interaktive Hilfe über MATLAB Funktionen zu erhalten. Das
helpwin-System ist das interaktive Analog des help-Systems. Durch Doppelklicken
auf ein Thema in diesem Textfenster, erhält man eine Liste zu diesem Thema. Der
helpwin-Befehl läßt sich analog dem help-Befehl mit dem gewünschten Thema
bzw. der gewünschten Funktion direkt aufrufen.
• Das Hilfesystem helpdesk
Das MATLAB-Hilfesystem helpdesk liefert HTML-basierte Hilfe. Diese HTMLDokumente haben den Vorteil, dass sie Grafiken beinhalten können und Verweise
auf andere Dokumente leicht machbar sind.
6
Abbildung 1.3: Help.
Kapitel 2
Erste Schritte
Der MATLAB-Prompt (die Eingabeaufforderung) wird durch die Zeichen “»“ gekennzeichnet. Das Semikolon “;“ trennt mehrere Befehle in einer Zeile, und unterdrückt die
Ausgabe von Werten, wohingegen das Komma “,“ Befehle trennt, aber die Werte auch
ausgibt. Zuweisungen erfolgen durch den Operator “=“. Drei Punkte am Zeilenende “...“
bedeutet, dass der Ausdruck in der nächsten Zeile weitergeht. Kommentare werden mit
“%“ eingeleitet.
MATLAB unterscheidet zwischen Groß- und Kleinbuchstaben, d.h. “Antwort“ und
“antwort“ sind unterschiedliche Variablennamen. Folgende Regeln sind bei der Definition
von Variablen zu beachten:
• Ein Variablenname darf keine Sonderzeichen außer dem Unterstrich enthalten.
• Das erste Zeichen muß ein Buchstabe sein.
• Der Name darf nicht mehr als 19 Zeichen enthalten (der Rest wird automatisch
abgeschnitten).
D.h. “test_3“ wäre ein gültiger Variablenname, aber “Summe_a+b“ oder auch “5_Test“
sind keine gültigen Variablennamen.
7
8
2.1
Einfache Rechenoperationen
Alle Anweisungen werden nach dem Prompt eingegeben und mit “Return“ bestätigt.
MATLAB nennt das Ergebnis ans (kurz für answer):
>> 12+3*1/8
ans =
12.3750
Addition (+), Subtraktion (-), Multiplikation (*) und Division (/) werden wie gewohnt
bezeichnet und verwendet.
Benötigt man einen Ausdruck häufiger, so ist es sinnvoll eine Variable anzulegen:
>> a_1 = 12+3*1/8; b_1 = 9/5+2/3
b_1 =
2.4667
Durch das Semikolon hinter der ersten Zuweisung wird die Ausgabe unterdrückt. Trotzdem ist die Variable “a_1“ definiert. Der Wert einer Variablen kann auch abgefragt werden:
>> a_1
a_1 =
12.3750
Wichtig: Bei der Multiplikation darf das Multiplikationszeichen (*) nicht weggelassen
werden:
9
>> 8a_1
??? 8a_1
|
Error: Unexpected MATLAB expression.
wohingegen
>> 8*a_1
ans =
99
2.2
Komplexe Zahlen
Komplexe Zahlen können wie reelle Zahlen eingegeben werden:
>> z1 = 3+4*j, z2 = 1-3i
z1 =
3.0000 + 4.0000i
z2 =
1.0000 - 3.0000i
Beachten Sie, dass die imaginäre Einheit als “i“ oder “j“ eingegeben werden kann (intern
wird “i“ verwendet). Außerdem kann das Multiplikationszeichen zwischen “i“ und dem
Imaginärteil weggelassen werden. Im Fall a = 1; b = 2; z = a + b ∗ j ist das Multiplikationszeichen zwischen b und “j“ jedoch notwendig.
Addition, Subtraktion, Multiplikation, Division und Funktionswerte werden wie bei
den reellen Zahlen gebildet:
10
>> z = z1/3 + z2*z1^2
z =
66.0000 +46.3333i
>> sqrt(1+2i)
ans =
1.2720 + 0.7862i
Die konjugiert komplexe Zahl zu z erhalten wir mit
>> z = 1+3i; conj(z)
ans =
1.0000 - 3.0000i
Auch durch Anfügen eines Apostrophs ’ wird eine Zahl komplex konjugiert. Das ist ein
Spezialfall - im allgemeinen bewirkt A′ , daß die Matrix A transponiert und komplex konjugiert wird.
>> z’
ans =
1.0000 - 3.0000i
Absolutbetrag und Phasenwinkel berechnet man mit abs(z) und angle(z), wobei der Phasenwinkel von MATLAB im Bogenmaß ausgegeben wird.
>> abs(z)
ans =
11
3.1623
>> angle(z)
ans =
1.2490
2.3
Vektoren
Vektoren werden genau wie Skalare als spezielle Matrizen behandelt. Dabei wird strikt
zwischen Zeilenvektoren (1 × n Matrizen) und Spaltenvektoren (n×1 Matrizen) unterschieden. Die Eingabe von Zeilenvektoren erfolgt durch
>> z=[1 2 5 7]
z =
1 2 5 7
bzw.
>> z=[1,2,5,7]
z =
1 2 5 7
Bei Spaltenvektoren müssen die Komponenten durch “;“ getrennt werden, d.h.
>> s=[1;2;3;4]
s =
1
2
3
4
12
Mit dem Befehl size ermittelt man das Format einer Variablen. Für s und z aus dem
vorherigen Beispiel erhalten wir
>> size(z),size(s)
ans =
1 4
ans =
4 1
d.h. z ist eine 1×4 Matrix, s eine 4×1 Matrix. Man beachte, daß das Ergebnis von size
selbst ein Vektor mit zwei Komponenten ist. Zeilenvektoren werden mit Hilfe des Transpositionsoperators ’ in Spalten umgewandelt und umgekehrt:
>> z,s
z =
1 2 5 7
s =
1
2
3
4
>> z’
ans =
1
2
5
7
>> s’
ans =
1 2 3 4
Vektoren gleichen Formats können addiert, subtrahiert und mit einer reellen Zahl multipliziert werden:
13
>> z=[1,2,5,7]
z =
1 2 5 7
>> z2=[5:8]
z2 =
5 6 7 8
>> z+z2
ans =
6 8 12 15
>> z*4
ans =
4 8 20 28
Das Skalarprodukt ergibt sich als Matrixmultiplikation eines Zeilenvektors mit einem
Spaltenvektor:
>> z,s
z =
1 2 5 7
s =
1
2
3
4
>> z*s
ans =
48
d.h. das Ergebnis ist eine 1×1 Matrix. Umgekehrt erhalten wir eine n×n Matrix, in unserem Beispiel also
>> s*z
ans =
14
1 2 5 7
2 4 10 14
3 6 15 21
4 8 20 28
Daneben gibt es die Möglichkeit, zwei Vektoren komponentenweise zu multiplizieren,
indem statt * der Operator .* benutzt wird:
>> z=[1,2,5,7]
z =
1 2 5 7
>> z2=[5:8]
z2 =
5 6 7 8
>> z.*z2
ans =
5 12 35 56
Auf ein einzelnes Element eines Vektors wird in Array-Notation zugegriffen:
>> z=[1,2,5,7]
z =
1 2 5 7
>> z(3)
ans =
5
Man beachte die runden Klammern! Die Indizierung beginnt bei 1 (nicht bei 0). Analog
kann man komplette Teilvektoren selektieren, z.B.
>> z=[1,2,5,7]
z =
1 2 5 7
>> z(1:3)
15
ans =
1 2 5
d.h. z(1 : 3) selektiert die Komponenten mit Index 1, 2, 3. Soll ein nicht zusammenhängender Bereich selektiert werden, so benutzt man einfach einen Indexvektor
>> z([1,3,4])
ans =
1 5 7
Neben dem Auswählen von Teilvektoren können Vektoren auch erweitert werden:
>> z=[1,2,5,7]
z =
1 2 5 7
>> z=[z,8,9]
z =
1 2 5 7 8 9
>> z2=[5:8]
z2 =
5 6 7 8
>> z=[z,z2]
z =
Columns 1 through 7
1 2 5 7 8 9 5
Columns 8 through 10
6 7 8
Bei allen Operationen mit Vektoren muß darauf geachtet werden, dass die (Matrix-) Formate mathematisch korrekt gewählt sind, d.h. man kann keine Spalten- zu Zeilenvektoren
addieren etc. Für Vektoren sind zahlreiche spezielle Funktionen implementiert, so z.B.
die Norm eines Vektors:
>> z=[1,2,5,7]
16
z =
1 2 5 7
>> norm(z)
ans =
8.8882
2.4
Matrizen
Für Matrizen gelten analoge Aussagen wie für Vektoren. Mit
>> a = [1 2 3;4 5 6]
a =
1 2 3
4 5 6
definiert man also eine 2×3 Matrix. Matrizen können auch aus Zeilen- bzw. Spaltenvektoren zusammengesetzt werden:
>> z1=[3 2 1]
z1 =
3 2 1
>> z2=[6 5 4];
>> b=[z1;z2]
b =
3 2 1
6 5 4
Man beachte, dass Zeilen mit “;“ aber Spalten mit “,“ getrennt werden müssen. Zur Selektion einzelner Elemente wird wieder Array-Notation benutzt, so dass für die Matrix b
aus dem letzten Beispiel folgt
>> b(2,1)
ans =
6
17
Analog zu Vektoren können Untermatrizen ausgewählt bzw. Matrizen erweitert werden.
Addition und Subtraktion zweier Matrizen sowie Multiplikation einer Matrix mit einer
reellen Zahl sind wie üblich definiert. Wie bei Vektoren können zwei Matrizen mit Hilfe
der Operatoren .* bzw. ./ komponentenweise multipliziert bzw. dividiert werden:
>> a,b
a =
1 2 3
4 5 6
b =
3 2 1
6 5 4
>> a.*b
ans =
3 4 3
24 25 24
Zum Transponieren einer Matrix benutzt man wieder den Operator ’.
Existiert die Inverse A−1 , so ist die Lösung x von A∗x = b gegeben durch x = A−1 ∗b.
A ist invertierbar genau dann, wenn die Determinate von A ungleich Null ist:
>> A= [3 4 -2; -1 2 8; 2 0 -5], b = [4; -1; 3]
A =
b =
3
4
-2
-1
2
8
2
0
-5
18
4
-1
3
>> det(A)
ans =
22
Wir erhalten die Inverse A−1 mit inv(A):
>> x = inv(A)*b
x =
2.1818
-0.5000
0.2727
MATLAB bietet noch eine andere Schreibweise für x = A−1 ∗ b:
>> x = A\b
x =
2.1818
-0.5000
0.2727
Das Symbol “\“ bezeichnet die sogenannte Linksdivision (left division). Der Name kommt
daher, dass nun der Nenner links steht und der Bruchstrich nach links geneigt ist. Hier
steht A\ sozusagen für die Inverse von A. Im Fall von Skalaren ist die Linksdivision
>> 2\3
19
ans =
1.5000
gleich der Rechtsdivision 3/2 (die Multiplikation von Skalaren ist ja kommutativ). Bei
Matrizen aber ist inv(A) ∗ b (Linksdivision) ungleich b ∗ inv(A) (Rechtsdivision), der
letzte Ausdruck ist nämlich gar nicht definiert. Daher erhalten wir eine Fehlermeldung,
wenn wir eingeben:
>> b/A
??? Error using ==> /
Matrix dimensions must agree.
Die Verwendung von x = A\b anstelle von x = inv(A) ∗ b hat verschiedene Vorteile:
• Erstens werden bei Eingabe von A\b weniger interne Rechenschritte durchgeführt
(es wird das Gaußsche Eliminationsverfahren verwendet). Daher erhält man so vor
allem bei größeren Problemen schneller eine Lösung.
• Zweitens liefert die Eingabe von x = A\b auch dann eine Lösung, wenn das Gleichungssystem nicht eindeutig lösbar ist (und daher die Inverse A−1 nicht existiert).
Im Fall eines überbestimmten Systems erhält man zum Beispiel eine Lösung, die
den quadratischen Fehler von Ax − b = 0 minimiert.
Es gibt einige Funktionen zum einfachen erzeugen spezieller Matrizen:
>> ones(2,3)
ans =
1 1 1
1 1 1
>> zeros(3,2)
ans =
0 0
0 0
20
0 0
>> eye(3)
ans =
1 0 0
0 1 0
0 0 1
>> rand(3,2)
ans =
0.4398 0.3651
0.3400 0.3932
0.3142 0.5915
MATLAB erlaubt es, daß Funktionen mehrere Ergebniswerte liefern, die in einem Vektor
zusammengefasst werden. Ein Beispiel dafür ist die (eingebaute) LU-Zerlegung einer
Matrix A, d.h. P A = LU , wobei A die Eingabe und P, L, U Ausgabewerte sind. Ein
entsprechender Aufruf der Funktion lu sieht wie folgt aus:
>> A=3*eye(3)+ones(3)
A =
4 1 1
1 4 1
1 1 4
>> [L,U,P] = lu(A)
L =
1.0000 0 0
0.2500 1.0000 0
0.2500 0.2000 1.0000
U =
4.0000 1.0000 1.0000
0 3.7500 0.7500
0 0 3.6000
P =
21
1 0 0
0 1 0
0 0 1
Weitere Details sind mit help lu zu erhalten. Darüberhinaus sind die meisten Standardfunktionen (exp, sin, cos, etc.) auf Matrizen definiert, wobei sie jeweils komponentenweise angewandt werden. Bei allen Operationen mit Matrizen muss darauf geachtet werden,
dass die Matrix-Formate mathematisch korrekt gewählt sind.
2.5
Lösung von Gleichungen
Die Anweisung solve(f,’x’) löst die symbolische Gleichung f nach x auf. Kommt nur eine
Variable vor, so wird automatisch nach ihr aufgelöst und es genügt der Befehl solve(f).
• Die lineare Gleichung 3x + 4 = 17 wird gelöst mit:
>> solve(’3*x + 4 = 17’)
ans =
13/3
Die einfachen Anführungszeichen sind hier notwendig, damit das Gleichheitszeichen nicht als Zuweisung interpretiert wird.
• Geben wir beim nächsten Beispiel, der Exponentialgleichung 5x−1 = 10, eine der
Zahlen als Kommazahl ein:
>> f = ’5^(x-1) = 10’; solve(f)
ans =
log(5, 10) + 1
22
im Gegensatz zu
>> f = ’5.0^(x-1) = 10’; solve(f)
ans =
2.4306765580733930506701065687640
Nun wird, da die Zahl 5 in der Form 5. eingegeben worden ist, auch das Ergebnis
numerisch ausgegeben. Auch mit double kann ein numerisches Ergebnis ausgegeben werden.
• Mehrere Lösungen gibt es in folgendem Beispiel, bei dem die Schnittpunkte von
tan(2x) und sin(x) berechnet werden:
>> solve(’tan(2*x) = sin(x)’)
ans =
acos(1/2 - 3^(1/2)/2)
acos(3^(1/2)/2 + 1/2)
0
-acos(1/2 - 1/2*3^(1/2))
-acos(1/2*3^(1/2) + 1/2)
>> double(ans)
ans =
1.9455
0 + 0.8314i
0
23
-1.9455
0 - 0.8314i
Es werden also sowohl die reellen als auch die komplexen Lösungen ausgegeben!
Natürlich kann auf eine bestimmte Lösung zugegriffen werden:
>> w = ans(2)
w =
3.1416
• MATLAB kann nicht immer alle Lösungen ausgeben. So hat zum Beispiel die trigonometrische Gleichung sin(3x + 1.2) = 0 unendlich viele Lösungen:
>> solve(’sin(3*x + 1.2) = 0’)
ans =
-.40000000000000000000000000000000
MATLAB berechnet hier aber nur eine Nullstelle!
• Ein Gleichungssystem bestehend aus den symbolischen Gleichungen g1, g2, g3 wird
mit solve(g1,g2,g3,’x,y,z’) nach den Variablen x, y und z aufgelöst. Kommen sonst
keine Variablen vor, so genügt die Anweisung solve(g1,g2,g3):
>> g1 = ’x + y + z = 0’;
>> g2 = ’4*x + 5*y + z - 3 = 0’;
>> g3 = ’-2*x + y - 3*z - 5 = 0’;
>> [x y z]= solve(g1,g2,g3)
x =
-1
24
y =
3/2
z =
-1/2
2.6
Ableiten
Die Anweisung diff bildet die Ableitung eines symbolischen Ausdrucks :
>> syms x; diff(cos(x))
ans =
-sin(x)
>> diff(sqrt(5*x^2 - 7*x + 4))
ans =
(10*x - 7)/(2*(5*x^2 - 7*x + 4)^(1/2))
Im nächsten Beispiel kommen in der Funktion zwei Variablen, x und t, vor. Wir müssen
daher angeben, nach welcher Variablen differenziert werden soll:
>> syms t; diff(3*x*t,x)
ans =
3*t
25
Möchte man eine höhere Ableitung berechnen, so gibt man das zusätzlich in der Klammer
an:
>> diff(cos(x),2)
ans =
-cos(x)
Hier wird 2-mal differenziert.
2.7
Integration
Mit der Anweisung int wird ein symbolischer Ausdruck integriert:
>> syms x; int(log(x))
ans =
x*(log(x) - 1)
Nun wollen wir y = t ∗ x3 nach t integrieren. Da hier zwei Variable t und x vorkommen,
müssen wir angeben, dass wir nach t integrieren wollen:
>> syms t; int(t*x^3,t)
ans =
(t^2*x^3)/2
Um bestimmt zu integieren, etwa von 0 bis 1, geben wir zusätzlich die Integrationsgrenzen
an:
>> int(x^2,0,1)
26
ans =
1/3
2.8
Grenzwertbestimmung
Grenzwerte (auch einseitige) können ebenfalls symbolisch mit der limit-Anweisung berechnet werden:
>> syms x a; limit(sin(a*x)/x, x,0)
ans =
a
Das erste Argument gibt hierbei die Funktion an, deren Grenzwert bestimmt werden soll.
Das zweite und dritte Argument spezifizieren welche Variable sich welchem Wert nähern
soll. Durch Hinzufügen von “right“ oder “left“ werden die entsprechenden einseitigen
Grenzwerte bestimmt:
>> syms t; limit(1/(t-1),t,1,’right’)
ans =
Inf
Kapitel 3
Graphiken und Funktionen
3.1
Graphiken
Mit der Funktion plot können in MATLAB Polygonzüge durch gegebene x-y Wertepaare
gezeichnet werden. Um den Graphen von sin(x) auf dem Intervall [0, 2π] zu zeichnen
konnen wir folgende Kommandos benutzen:
>> x=[0:0.1:2*pi];
>> y=sin(x);
>> plot(x,y)
Mit dem ersten Befehl werden x-Werte zwischen 0 und 2π mit Abstand 0.1 erzeugt.
Der zweite Befehl generiert die zugehörigen Funktionswerte. Mit plot(x,y) öffnet sich
ein neues Fenster und der Polygonzug wird blau in ein Koordinatensystem eingezeichnet
(siehe Abbildung 3.1).
Erzeugen wir anschließend einen zweiten Satz von Funktionswerten z.B. für cos(x)
und plotten den neuen Graphen, so erscheint er im selben Grafikfenster, aber die alte Grafik wird vorher gelöscht. Um beide Kurven ins selbe Grafikfenster zu zeichnen, müssen
wir den Befehl “hold on“ benutzen. Nach “hold on“ erfolgen sämtliche plot Ausgaben ins
selbe Koordinatensystem im momentan aktiven Grafikfenster. Das kann durch “hold off“
wieder rückgängig gemacht werden, d.h. nach “hold off“ wird bei jedem plot Befehl der
Fensterinhalt zuerst gelöscht. Wenn also nacheinander erst der sinus (in blau) und dann
der cosinus (in rot) ins selbe Fenster gezeichnet werden soll, dann benutzen wir:
27
28
Abbildung 3.1: sin(x).
>> x=[0:0.1:2*pi];
>> y=sin(x);
>> plot(x,y)
>> hold on
>> z=cos(x);
>> plot(x,z,’r’)
>> hold off
und erhalten den Graphen in Abbildung 3.2. Alternativ geht auch
>> x=[0:0.1:2*pi];
>> y=sin(x);
>> z=cos(x);
>> plot(x,y,x,z,’r’)
Eine Funktion kann auch gezeichnet werden, ohne daß Datenpunkte angegeben werden müssen. Dies ist mit der Anweisung fplot möglich. Mit ihr kann man Funktionen
zeichnen, ohne vorher einen Vektor x definieren zu müssen. MATLAB wählt die Stellen,
an denen die Funktionswerte berechnet werden, automatisch. Gezeichnet wird die Funktion hier für −20 ≤ x ≤ 20 mit einem sichtbaren Wertebereich von −0.4 ≤ y ≤ 1.2
(siehe Abbildung 3.3).
29
Abbildung 3.2: cos(x) und sin(x) im gleichen Koordinatensystem.
>> fplot(’sin(x)./x’, [-20,20,-0.4,1.2])
Abbildung 3.3: sin(x)/x.
Es kann vorteilhaft sein, eine oder beide Achsen eines rechtwinkligen Koordinatensystems logarithmisch zu skalieren. So wird eine Exponentialfunktion y = aebx in einem
„ordinatenlogarithmischen Papier“ (d.h. die y-Achse ist logarithmisch geteilt) als Gerade
dargestellt.
>> x = linspace(0,10,50);
30
>> y = 3*exp(-0.5*x);
>> semilogy(x,y); grid
Hier besteht der Vektor x aus 50 Werten im gleichen Abstand, wobei der erste Wert 0
und der letzte Wert 10 ist. Fehlt die Angabe für die Anzahl der Werte, so wird dafür 100
genommen. Abbildung 3.4 zeigt das Resultat.
Abbildung 3.4: Semilogplot von y = aebx .
Will man eine Funktion z = f (x, y) graphisch veranschaulichen, so kann man den
Graph dieser Funktion, eine Fläche, über der (x, y)-Ebene zeichnen. Dazu ist anzugeben,
über welchem x-Bereich und y-Bereich gezeichnet werden soll. Wir wollen die Funktion
z = xy zuerst sehr grobflächig als Maschenplot (Drahtgitter) über den folgenden 15 Gitterpunkten (−2/−1), (−2/0), ..., (2/1) zeichnen, die aus den fünf x-Werten 2, −1, 0, 1, 2
sowie den drei y-Werten 1, 0 und 1 gebildet werden können.
>> x = -2:1:2
>> y = -1:1:1
>> [xx, yy] = meshgrid(x,y)
x =
31
-2
-1
0
1
2
-1
0
1
-2
-1
0
1
2
-2
-1
0
1
2
-2
-1
0
1
2
-1
-1
-1
-1
-1
0
0
0
0
0
1
1
1
1
1
y =
xx =
yy =
Von besonderer Bedeutung ist hier die Anweisung meshgrid (mesh = Masche, grid =
Gitter). Es erzeugt zwei Matrizen, hier xx und yy genannt. Einander entsprechende Elemente dieser beiden Matrizen bilden gerade die beiden Koordinaten unserer Gitterpunkte.
Anwendung der Punktmultiplikation ergibt:
>> z = xx.*yy
z =
2
1
0
-1
-2
0
0
0
0
0
32
-2
-1
0
1
2
Dies sind die gewünschten Funktionswerte. Zuletzt soll jeder dieser Funktionswerte über
„seinem“ Gitterpunkt als Punkt dargestellt und in x- und in y-Richtung durch Strecken mit
den Nachbarpunkten verbunden werden. Wir erhalten den Maschenplot oder das Drahtmodell der Funktion. Dies erfolgt mit Hilfe der Anweisung mesh:
>> mesh(x,y,z)
2
1
0
−1
−2
1
0.5
2
1
0
0
−0.5
−1
−1
−2
Abbildung 3.5: Maschenplot von f(x,y)=xy.
x und y geben die x- bzw. die y-Werte der Gitterpunkte an, z die Funktionswerte über
den Gitterpunkten.
Statt die Punkte durch Strecken zu verbinden, können auch kleine Flächenstücke zwischen den Punkten verwendet werden. Man erhält so ein Kachelmodell der Funktion,
indem man mesh durch surf (von surface) ersetzt. Im Folgenden ist die Fläche außerdem
durch mehr Gitterpunkte feinmaschiger gezeichnet und die Achsen sind beschriftet.
>> x = -2:0.2:2; y = -1:0.2:1;
>> [xx,yy] = meshgrid(x,y,z);
>> z = xx.*yy;
>> surf(x,y,z); xlabel(’x’); ylabel(’y’); zlabel(’z’)
33
2
z
1
0
−1
−2
1
0.5
2
1
0
0
−0.5
y
−1
−1
−2
x
Abbildung 3.6: Surfaceplot von f(x,y)=xy.
Der plot Befehl läßt noch zahlreiche Optionen zu. Nach dem Zeichnen von Grafiken können diese auch noch mit dem title bzw. legend Befehl beschriftet werden. Außerdem kann
der Inhalt eines Grafikfensters auch in vielen gängigen Grafikformaten (ps, jpeg, etc.) abgespeichert werden. Details sind mit der help Funktion zu erfahren.
3.2
Funktionen
Funktionen sind analog zu anderen prozeduralen Programmiersprachen aufgebaut, d.h.
die Schnittstelle wird durch Funktionsname, Eingabe- und Ergebnisparameter festgelegt,
wobei keine Typen angegeben werden müssen. Der File-Name und der Funktionsname
müssen übereinstimmen. In der Regel wird jede Funktion in ein eigenes m-File in den
Arbeitsbereich gelegt. Als Beispiel betrachten wir die Definition der Funktion
f (x) = 0.01 ∗ (50 − x) ∗ x
Um ein neues m-File zu erzeugen klickt man mit der rechten Maustaste in das linke obere
Fenster (Current Directory), worauf ein Menü erscheint, in dem der Punkt “New File –
Blank M-File“ angewählt werden muß. Anschließend wird ein File mit einem DefaultNamen generiert, den wir z.B. auf “f.m“ ändern. Durch Doppelklick auf das f.m Icon
wird die Datei nun in einem gesonderten Editor-Fenster geöffnet.
34
Abbildung 3.7: Neues m-file.
Als erstes definieren wir in der ersten Zeile die korrekte Schnittstelle für unsere Funktion, d.h.
function y = f(x)
da wir einen Eingabe- und einen Ausgabeparameter benutzen wollen. Die nächsten Zeilen sollte man für Funktionsdokumentation (Kommentarzeilen werden mit % eingeleitet)
nutzen (nicht zwingend notwendig, aber sinnvoll). Rufen wir später help f auf, so wird
diese Dokumentation angezeigt. Wir können unsere Funktion f z.B. wie folgt vereinbaren
(siehe Abbildung 3.8):
Die Variablen a und g, die in der Funktion vereinbart sind, werden als lokale Variablen behandelt, d.h. außerhalb der Funktion sind sie nicht sichtbar. Man beachte, daß bei
der Multiplikation der Operator .* benutzt wurde, damit die Funktion (wie die Standardfunktionen sin, cos, etc.) auch komponentenweise auf Vektoren und Matrizen angewandt
werden kann. Das m-File muss explizit abgespeichert werden. Anschließend kann f wie
35
Abbildung 3.8: Definition der Funktion.
gewohnt benutzt werden
>> f(1)
ans =
0.4900
>> x=[1:4]
x =
1 2 3 4
>> f(x)
ans =
0.4900 0.9600 1.4100 1.8400
Als Hilfetext erhalten wir
>> help f
36
y = f(x)
berechnet f(x) = 0.01 * (50-x) * x
3.3
Gewöhnliche Differentialgleichungen
MATLAB hat mehrere vordefinierte Funktionen zur näherungsweisen Lösung von Anfangswertproblemen für Systeme von Differentialgleichungen erster Ordnung. Eine dieser Funktionen ist ode45 mit Schnittstelle
[t,x]=ode45(@f,[t0,te],x0)
Die Eingabeparameter sind
• f , eine Funktion f (t, x) die von t und x abhängt und die rechte Seite der Differentialgleichung enhält,
• [t0, te], ein zweidimensionaler Vektor, der Anfangs und Endzeit enthält,
• x0, der Anfangswert.
Als Ausgabe erhalten wir einen Vektor t, der Zeitpunkte zwischen t0 und te enthält, sowie
x, das die zugehörigen (genäherten) Funktionswerte der Lösung x an den Zeitpunkten von
t enthält. Dabei treten folgende Besonderheiten auf:
• werden Funktionen als Parameter an andere Funktionen übergeben, so geschieht
dies (analog zu C) über einen Funktionszeiger, den wir durch das “@“ Zeichen vor
dem Funktionsnamen erhalten ,
• f muß immer t und x als Parameter besitzen, auch wenn es nur von einer der beiden
Variablen (oder auch von keiner) abhängt,
• der Zeitvektor [t0, te] darf sowohl ein Spalten- als auch ein Zeilenvektor sein,
• lösen wir ein System, so ist x(t) und damit auch x0 vektorwertig; ode45 verlangt,
daß es sich hierbei um Spaltenvektoren handelt.
37
Um das Grenzpopulationsproblem
x’ = a*(g-x)*x, x(0)= 10
für a = 0.01, g = 50 auf dem Zeitintervall T = [0, 20] anzunähern, ändern wir zunächst
unsere oben definierte Funktion f ab zu
function y = f(t,x)
%y = f(t,x)
% berechnet f(t,x) = 0.01 * (50-x) * x
a=0.01;
g=50;
y=a*(g-x).*x;
und benutzen dann folgende Befehle
>> T=[0,20];
>> x0=10;
>> [t,x]=ode45(@f,T,x0);
>> plot(t,x)
so erhalten wir als Ausgabe den Graphen in Abbildung 3.9.
Um die Modellparameter a und g nicht fest in f kodieren zu müssen, vereinbart man
sie als globale Variablen. Dazu muss f zuerst mitgeteilt werden, dass es sich um globale
Variablen handelt:
function y = f(t,x)
%y = f(t,x)
% berechnet f(t,x) = a * (g-x) * x
global a g;
y=a*(g-x).*x;
Zusätzlich muß im Kommandofenster ebenfalls der “global“ Befehl abgesetzt werden und
anschließend den Variablen ein Wert zugewiesen werden:
38
Abbildung 3.9: Lösung der ODE.
>> global a g
>> a=0.01;g=75;
Dabei sind einige Besonderheiten zu beachten:
• nach der “global“ Vereinbarung haben unbedingt Zuweisungen an die globalen Variablen zu erfolgen; eventuell vorher zugewiesene Werte sind nach global nicht
sichtbar
• alle Änderungen an globalen Variablen, die nach der global Vereinbarung erfolgen,
sind systemweit sichtbar
• die Variablen in “global“ dürfen nicht durch Komma getrennt werden.
Kapitel 4
MATLAB als Programmiersprache
Einfache Funktionen, die in m-files abgespeichert werden, haben wir ja bereits im letzten Kapitel gesehen. In diesem Kapitel werden nun wichtige Kontrollmechanismen zur
Steuerung des Ablaufes von MATLAB-Anweisungen vorgestellt. Von diesen Mechanismen wird innerhalb von Funktionen massiv gebraucht gemacht.
4.1
If-Abfragen
If-Abfragen führen zu bedingten Verzweigungen innerhalb eines Programmablaufes. Die
Verzweigung erfolgt in Abhängigkeit eines bestimmten Testresultats. Diese If-Abfragen
tauchen typischerweise in Situationen auf, in denen fehlerhafte Eingaben behandelt werden müssen, um größerem Unheil vorzubeugen bzw. die Korrektheit des zugrundeliegenden Algorithmus zu garantieren. Ein klassisches Beispiel für den ersten Fall ist die
Operation der Division a/b einer Zahl a dividiert durch b. Man will natürlich nur durch
b dividieren, falls b nicht Null ist. Anderenfalls verzichten wir auf die Division. Die entsprechende Folge von MATLAB-Anweisungen sieht für diesen Fall folgendes vor:
>> if b ~= 0
c = a/b;
end
wobei wir angenommen haben, daß die Variablen a und b dem MATLAB-Interpreter bereits bekannt sind. Der Test in dieser If-Abfrage lautet b ˜= 0: es wird geprüft, ob b un39
40
gleich Null ist. Fällt dieser Test positiv aus (d.h. b ist nicht Null), so wird in die Zeile
c = a/b; verzweigt. Jede If-Abfrage endet generell mit der Anweisung end.
Mit dem obigen Beispiel haben wir bereits den Relationsoperator ˜= (ungleich) kennengelernt. Dieser liefert im obigen Fall das Resultat 1, falls b 6= 0, ansonsten das Resultat
0. Mit anderen Worten: Der Test b ˜= 0 fällt positiv aus, falls die Operation b ˜= 0 den
Wert 1 liefert; der Test b ˜= 0 fällt negativ aus, falls die Operation b ˜= 0 den Wert 0 liefert.
Weitere Relationsoperatoren in MATLAB sind die folgenden:
<
kleiner
>
größer
<= kleiner oder gleich
>= größer oder gleich
==
˜=
gleich
ungleich
Ein weiteres Beispiel, das an das obige anknüpft: Wir wollen der Variablen c den Wert
der Division a/b zuweisen, falls b nicht Null ist, anderenfalls wollen wir c den Wert Null
zuweisen. Mit MATLAB sieht die entsprechende Anweisungsfolge wie folgt aus.
>> if b ~= 0
c = a/b;
else
c = 0;
end
Ein weiteres Beispiel: Wir wollen die Vorzeichenfunktion implementieren: Wir weisen
der Variablen s den Wert −1 zu, falls die Variable x einen negativen Wert besitzt, s bekommt den Wert 1, falls der Wert von x positiv ist; anderenfalls (d.h. falls x den Wert
Null besitzt), bekommt s den Wert Null zugewiesen.
>> if x < 0
s = -1;
41
elseif x > 0
s = 1;
else
s = 0;
end
4.2
For-Schleifen
Wollen wir eine bestimmte Folge von Anweisungen n-mal hintereinander ausführen, so
bietet sich die Verwendung einer sogenannten For-Schleife an. Nehmen wir an, wir wollen elf ganzzahlige Zufallszahlen aus dem Intervall [0, 2] erzeugen (um etwa am Totowettbewerb teilzunehmen). Eine mögliche Implementation mit einer For-Schleife sieht
folgendermaßen aus.
Beipiel 1: Elf Totozahlen zufällig generieren. Der Vektor x enthält nach Ablauf der
For-Schleife die elf Zufallszahlen.
>> x = [];
>> for k=1:11
x = [x; round(2*rand)];
end
>> x
x =
2
2
0
2
1
0
1
42
1
2
2
0
Beipiel 2: Wir berechnen die Zahl 12! = 1 ∗ 2 ∗ . . . ∗ 12. Die Hilfsvariable “fac“ wird das
Ergebnis enthalten.
>> n = 12;
>> fac = 1;
>> for i=2:n
fac = i*fac;
end
>> fac
fac =
479001600
Nun brauchen wir die Variable “fac“ nicht mehr.
>> clear fac;
4.3
While-Schleifen
Wir haben im vorigen Unterabschnitt For-Schleifen kennengelernt. While-Schleifen sind
so ähnlich: Während man bei einer For-Schleife bereits vor deren Ablauf weiß, wie oft
man den Schleifenkörper durchlaufen möchte, koppelt man dies bei While-Schleifen an
eine Bedingung: Vor jedem Durchlaufen des Schleifenkörpers findet ein Test statt. Fällt
der Test positiv aus, so wird der Schleifenkörper durchlaufen. Anderenfalls wird die
While-Schleife verlassen (oder erst gar nicht betreten), und die Anweisungen nach der
While-Schleife werden ausgeführt.
43
Ein Negativbeispiel: Wir produzieren absichtlich eine Endlosschleife (wenn Sie noch
nicht wissen, was eine Endlosschleife ist, dann werden Sie es gleich wissen) mit der
folgenden Anweisungssequenz.
>> n = 1;
>> while n > 0
n = n + 1;
end
Mit der Tastenkombination CTRL + C kann man die aktuelle Berechnung abbrechen,
und bekommt den vertrauten MATLAB-Prompt zurück, d.h. man kann anschließend die
begonnene MATLAB-Sitzung fortführen.
Ein weniger destruktives Beispiel: Wir wollen zu einer positiven Zahl x die kleinste
ganze Zahl n mit der Eigenschaft n < x < n + 1 berechnen. Zur Information: Üblicherweise kürzt man diese Zahl mit [x] ab, und das Symbol [·] wird als Gaußklammer
bezeichnet.
>> x = 5.3;
>> n=0;
>> while n+1 <= x
n = n+1;
end
>> n
n =
5
Selbstverständlich ist [x] auch für negative reelle Zahlen definiert. Diese mögliche Erweiterung der obigen Implementation von [x]sieht beispielsweise so aus:
>> x = - 5.3;
>> n=0;
44
>> if x < 0
while n > x
n = n-1;
end
elseif x > 0
while n+1 <= x
n = n+1;
end
end
>> n
n =
-6
Sie werden es zurecht als umständlich empfunden haben, die einzelnen Anweisungen,
die mit If-Anweisungen sowie For- und While-Schleifen verbunden sind, Zeile für Zeile
an den Interpreter zu übergeben. Wie bereits eingangs erwähnt, tauchen solche Kontrollstrukturen üblicherweise innerhalb von Funktionen auf.
4.4
Abbruch von Schleifen
Für den Fall, daß man den Ablauf einer For- oder einer While-Schleife aus irgendwelchen
Gründen terminieren lassen möchte, steht in MATLAB der Befehl break zur Verfügung.
Diese Art von Abbruch kann sinnvoll sein in Anwendungen, die mit Suchen oder Zählen
in Verbindung stehen. Hierzu jeweils ein Beispiel.
Beipiel 3: Ein Suchbeispiel mit einer For-Schleife. Man möchte zu einem Zeilenvektor
x, dessen Komponenten Zufallszahlen aus dem Intervall [0, 1] sind, dessen kleinsten Index
i ermitteln, für den gilt x(i) < 0.5. Falls es keinen solchen Index gibt, so soll i den Wert
−1 besitzen.
>> n = 10;
45
>> x = rand(1,n)
>> i = -1;
>> for k=1:n
if x(k) < 0.5
i = k;
break;
end
end
>> i
x =
Columns 1 through 5
0.0357
0.8491
0.9340
0.6787
0.7577
0.6555
0.1712
0.7060
Columns 6 through 10
0.7431
0.3922
i =
1
Beipiel 4: Ein Zählbeispiel mit einer While-Schleife. Man möchte solange Zufallszahlen
aus [0, 1] erzeugen, bis eine der Zufallszahlen größer als 0.99 ist. Die Anzahl n der Versuche sollen mitgezählt und anschließend anzeigt werden; Falls die Anzahl der Versuche
10 übersteigt, so möchte man aufhören.
>> x = rand;
>> n = 1;
46
>> while x <= 0.99
if n > 10
n = - 1;
break;
else
x = rand;
n = n+1;
end;
end;
>> n
n =
-1
Herunterladen