Ing Mathematik: Numerische Mathematiksysteme am Beispiel von Octave
Hallo Welt und allgemeine Hinweise
[Bearbeiten]Was ist Octave
[Bearbeiten]- Octave ist eine Software zur numerischen Lösung mathematischer Probleme.
- Octave ist Open-Source (GPL-Lizenz).
- Octave ist für viele Betriebssysteme erhältlich (z.B. für Linux, MS Windows, macOS).
- Octave ist weitgehend kompatibel zum Numerik-Standardprogramm MATLAB.
- Octave ist ein Interpreter.
- Octave als Programmiersprache ist case-sensitive - d.h. Groß- und Kleinschreibung ist relevant bei der Eingabe von Befehlen.
.
Octave installieren
[Bearbeiten]MS Windows
[Bearbeiten]Laden Sie das aktuelle Octave-Paket von der Webseite www.gnu.org/software/octave/ herunter. Weiter geht es wie bei jedem anderen größeren zu installierenden Programm. Einfach das Installationsprogramm im Explorer doppelklicken und den Anweisungen des Setup-Programmes folgen.
Linux
[Bearbeiten]Entweder ist Octave bereits standardmäßig installiert, ansonsten ist die Installation mittels Paketmanagementsystem einfach möglich.
Octave starten
[Bearbeiten]MS Windows
[Bearbeiten]Das Icon für das Octave-Programm doppelklicken (für das Konsolenprogramm ... CLI, für die grafische Benutzeroberfläche ... GUI). Und schon startet das Programm.
Linux
[Bearbeiten]In einer Linux-Konsole den Befehl "octave" eintippen und das Programm startet.
Ein paar Worte zur Erklärung
[Bearbeiten]Im Folgenden wird immer das Konsolenprogramm (CLI ... Command Line Interface) für die Eingabe von Befehlen benutzt. Erst gegen Ende dieses Textes wird auch kurz auf das GUI von Octave eingegangen.
Teilweise werden Ergebnisse der älteren Octave-Version 3.0.3 dargestellt. Aktuell ist mit Stand März 2024 die Version 9.1.0, die auch mit diesem Text abgedeckt werden soll. Die dargestellten Grafiken und Ausgabetexte können je nach Version leicht voneinander abweichen. Der Text wurde ursprünglich mit der Octave-Version 3.0.3 erstellt und anschließend auf die Versionen 5.2 bis 9.1.0 aktualisiert. Dieser Mischmasch sollte aber kein Problem darstellen.
Getestet wurden die Beispiele unter dem Betriebssystem MS Windows 10.
Ein erstes Programm
[Bearbeiten]Kommentare werden in Octave mit dem Prozentzeichen (%) oder alternativ mit der Raute (#) eingeleitet. Sie werden vom Octave-Interpreter ignoriert. Will man kompatibel mit MATLAB bleiben, so ist die Version mit dem %-Zeichen vorzuziehen. Text kann mit der disp-Funktion ausgegeben werden. Starten Sie Octave und geben sie folgende Anweisungen zeilenweise ein
octave-3.0.3.exe:1> % Das ist ein Kommentar octave-3.0.3.exe:2> # und das auch octave-3.0.3.exe:3> disp "Hallo Welt!"
Als Ergebnis erhalten Sie
Hallo Welt!
Der Prompt (z.B. octave-3.0.3.exe:1>) ist natürlich abhängig von der Octave-Version und den schon eingegebenen Zeilen. Er ist selbstverständlich nicht einzutippen, sondern wird vom Octave-System geliefert.
Strings können in Octave entweder in Anführungszeichen (") gesetzt werden oder in Hochkommatas('). In diesem Text wird die erste Variante bevorzugt eingesetzt.
Octave als Taschenrechner
[Bearbeiten]Allgemeines
[Bearbeiten]Wir wollen 3 * 5 berechnen. Dazu starten wir Octave. Geben Sie dann die Formel
octave-3.0.3.exe:1> 3 * 5
ein, drücken die Taste ENTER/RETURN und erhalten als Ergebnis
ans = 15
Auch kompliziertere Ausdrücke sind möglich. Beispielsweise mit Winkelfunktionen, Quadratwurzeln etc. Wir wollen nun den Ausdruck berechnen :
octave-3.0.3.exe:2> sin(sqrt(15)) ans = -0.6679
Octave kennt eine Handvoll von Konstanten, z.B.:
Zeilenweise Eingabe:
% Die Kreiszahl PI pi % Die Eulersche Zahl e % Zur Maschinengenauigkeit eps
Ausgabe:
ans = 3.1416 ans = 2.7183 ans = 2.2204e-016
"ans" steht übrigens für den Begriff "answer" (auf Deutsch "Antwort"). Mit "ans" kann wie mit jeder anderen Variable oder Konstanten weitergerechnet werden, z.B.:
Eingabe:
% Der Kreisradius sei 10 10 % Der Kreis-Umfang mit diesem Radius sei folgendes 2 * pi * ans
Ausgabe:
ans = 10 ans = 62.832
Die Ausgabe eines Befehls am Bildschirm (das "Echo") kann übrigens durch Anwendung des Semikolons (;) unterdrückt werden. Gezeigt werden soll dies nun mit Hilfe des obigen Beispiels. Es soll nur der Umfang ausgegeben werden, nicht der Radius.
Eingabe:
% Der Kreisradius sei 10 10; % Der Kreis-Umfang mit diesem Radius sei folgendes 2 * pi * ans
Ausgabe:
ans = 62.832
Vielleicht ist manchem die Genauigkeit, mit der Echo bzw. der Befehl disp Werte ausgibt, nicht ausreichend. Dem kann Abhilfe verschafft werden und zwar so:
Eingabe:
format short pi format long pi format longe pi % usw.
Ausgabe:
ans = 3.1416 ans = 3.14159265358979 ans = 3.14159265358979e+00
Beenden lässt sich das Octave-Programm durch Eingabe von quit oder exit (und natürlich zur Bestätigung die RETURN-Taste drücken).
Die Hilfefunktion von Octave
[Bearbeiten]Die Eingabe von help mit Angabe eines Funktionsnamens liefert detaillierte Infos zu der gesuchten Funktion.
Eingabe:
help sin
Ausgabe:
'sin' is a built-in function from the file libinterp/corefcn/mappers.cc -- Y = sin (X) Compute the sine for each element of X in radians. See also: asin, sind, sinh. Additional help for built-in functions and operators is available in the online version of the manual. Use the command 'doc <topic>' to search the manual index. Help and information about Octave is also available on the WWW at https://www.octave.org and via the help@octave.org mailing list.
Auch gibt es die doc-Funktion für eine vollständige Dokumentation des Octave-Systems, z.B.:
Eingabe:
doc
Ausgabe:
Aufgaben
[Bearbeiten]- Berechnen Sie mit Octave den Ausdruck .
- Berechnen Sie mit Octave den Ausdruck . Anmerkung: cosd erwartet den Parameter im Gradmaß (d für "degree"), sin erwartet den Parameter im Bogenmaß.
- Erkunden Sie die Fehlerfunktion "erf" mittels Octave-Hilfe.
Octave als Scriptsprache
[Bearbeiten]Häufig wird man aber kompliziertere Anweisungsfolgen verarbeiten müssen. Diese will man normalerweise nicht jedesmal neu eingeben, sondern in einer Datei speichern und diese Datei dann zur Ausführung bringen. Speichern Sie dazu folgenden Code in einer Textdatei, z.B. unter MS Windows als c:\tmp\test1.m
% Das ist ein Kommentar # und das auch disp "Hallo Welt!"
Skriptdateien müssen mit der Dateiendung .m versehen werden. In der Octave-Konsole fügen Sie den Dateipfad mittels
octave-3.0.3.exe:1> addpath("c:/tmp")
hinzu (es ist der UNIX-spezifische Slash (/) zu benutzen). Alternativ können Sie zumindest unter MS Windows auch einen Doppel-Backslash (\\) einsetzen. Oder Sie wechseln mittels cd c:/tmp
direkt ins Verzeichnis c:/tmp
.
Danach bringen Sie die Skriptdatei test1.m (sozusagen das Hauptprogramm) zur Ausführung
octave-3.0.3.exe:2> test1
Achtung: Die Datei (die Funktion oder das Hauptprogramm) ist in der Octave-Kommandozeile ohne .m-Dateiendung anzugeben. Wie erwartet ergibt sich folgende Ausgabe am Bildschirm
Hallo Welt!
Blockkommentare
[Bearbeiten]In neueren Octave-Versionen sind auch Blockkommentare möglich. Blockkommentare werden wie normale Kommentare vom Octave-Interpreter ignoriert.
%{ Das ist ein Blockkommentar %} #{ und das auch #}
Variablen
[Bearbeiten]Variablenbezeichner können aus Buchstaben (A-Za-z), Ziffern (0-9) und Underscores (_) bestehen, dürfen aber nicht mit einer Zahl beginnen.
Gültige Variablenbezeichner wären also:
xyz x1 _wert name_anzahl
Da Octave case-sensitiv ist, repräsentieren folgende Bezeichner verschiedene Variablen:
xyz XYZ xYz
Werte werden an Variablen mittels Gleich-Zeichen (=) zugewiesen. Im Folgenden wird der Code immer in der Datei c:\tmp\test1.m gespeichert.
x = 5 y = 10 z = x*y
Bringen Sie die Datei test1.m zur Ausführung so erhalten Sie folgende Bildschirmausgabe
x = 5 y = 10 z = 50
Normalerweise will man aber nur z anzeigen, die Werte von x und y sind ja bereits bekannt. Dazu fügen Sie an den Anweisungsenden, wie bereits weiter oben erwähnt, bei x und y jeweils ein Semikolon (;) an, um das Anweisungsende explizit zu markieren.
x = 5; y = 10; z = x*y
Nun erhalten Sie als Ergebnis nur noch
z = 50
Sie können auch mehrere Anweisungen in einer Zeile durch Semikolon getrennt schreiben.
x = 5; y = 10; z = x*y
Ausgabe:
z = 50
Auch aus der Programmiersprache C/C++ oder Java bekannte Konstrukte können Sie verwenden, z.B.
x = 5; % inkrementiere x ++x % x = x - 2 x -= 2
Bildschirmausgabe:
ans = 6 x = 4
Beachten Sie, dass mit dem =-Zeichen eine Wertezuweisung durchgeführt wird. Dies ist nicht äquivalent zum mathematischen =-Zeichen, wie am vorigen Beispiel zu ersehen ist.
Soll eine Anweisung auf mehrere Zeilen verteilt werden, z.B. weil sie zu lang ist, so kann dies durch Verwendung von drei Punkten (...) geschehen, wie nachfolgend dargestellt.
x = 5; y = 1000 * x + ... sin(x/2)
Ausgabe:
y = 5000.6
Diese Drei-Punkte-Methode soll nicht für in doppelte Anführungszeichen ("") eingeschlossene Strings verwendet werden. Diese Methode ist seit geraumer Zeit "deprecated" und funktioniert mit der Version 9.1.0 gar nicht mehr. Benutzen Sie statt dessen den Backslash (\):
txt = "xxxxxxxxxxxxxxxxxxxx\ yyyyyyyyyyyyyyyyy"
Ausgabe:
txt = xxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyy
Variablen sind nicht an einen bestimmten Datentyp gebunden, folgendes ist in Octave problemlos möglich:
wert = 10 wert = 35.5 wert = "Hallo" wert = pi
Ausgabe:
wert = 10 wert = 35.500 wert = Hallo wert = 3.1416
Der Befehl who
, bzw. whos
listet die gegenwärtig definierten Variablen, z.B.:
clear; a = 10.5; v = [1 2 3 4 5 12 13]; m = ["s1", "s2"; "s3", "s4"]; disp "***** Der Befehl who *****" who disp "***** Der Befehl whos *****" whos
Ausgabe:
***** Der Befehl who ***** Variables visible from the current scope: a m v ***** Der Befehl whos ***** Variables visible from the current scope: variables in scope: top scope Attr Name Size Bytes Class ==== ==== ==== ===== ===== a 1x1 8 double m 2x4 8 char v 1x7 56 double Total is 16 elements using 72 bytes
Hexadezimale und binäre Zahlen
[Bearbeiten]% Hexadezimale Zahl disp( 0xABC ) % Binäre Zahl disp( 0b1000011 )
Ausgabe (als Dezimalzahlen):
2748 67
Octave kann auch dezimale in binäre Zahlen etc. umwandeln:
dec2bin( 214 )
Ausgabe:
ans = 11010110
Siehe dazu in der Octave-Hilfe auch folgende Funktionen:
bin2dec, dec2base, dec2hex, hex2dec, base2dec
Zahlenkolonnen
[Bearbeiten]Eine Zahlenkolonne (oder ein Vektor) mit gleichen Abständen der Werte kann folgendermaßen erzeugt werden:
% a ... Startwert % b ... Schrittweite % c ... Endwert a = 0; b = 10; c = 100; x = a : b : c; disp(x);
Ausgabe:
0 10 20 30 40 50 60 70 80 90 100
Ähnliche Resultate lassen sich auch durch Anwendung der linspace-Funktion erhalten, z.B.:
% a ... Startwert % b ... Endwert % c ... Anzahl der Werte a = 0; b = 100; c = 11; v = linspace(a, b, c)
Ausgabe:
v = 0 10 20 30 40 50 60 70 80 90 100
Verzweigungen
[Bearbeiten]Die IF-Verzweigung
[Bearbeiten]Die IF-Verzweigung ist aus anderen Programmiersprachen bereits bekannt. In Pseudocode lässt sie sich folgendermaßen darstellen:
WENN bedingung TRUE führe block1 aus SONST führe block2 aus ENDE
Die test1.m-Datei laute also wie folgt:
x = 5; if x < 4 disp "x ist kleiner als 4"; else disp "Der else-Zweig wird ausgefuehrt"; disp "x ist groesser oder gleich 4"; end
Ausgabe:
Der else-Zweig wird ausgefuehrt x ist groesser oder gleich 4
Octave kennt eine Reihe von Vergleichs- und Verknüpfungsoperatoren:
- <, <= ... kleiner (gleich)
- >, >= ... größer (gleich)
- == ... gleich
- ~=, != ... ungleich
- &, && ... AND
- |, || ... OR
- ~, ! ... NOT
Beispielsweise:
a = 5; b = 9; if a<=10 & b!=7 disp("OK"); else disp("Nicht OK"); end
Ausgabe:
OK
Die SWITCH-Verzweigung
[Bearbeiten]In Pseudocode:
WECHSLE ZU var FALLS wert1 == var führe block1 aus FALLS wert2 == var führe block2 aus ... SONST führe blockn aus ENDE
Eine Beispielsimplementierung in Octave könnte so aussehen:
x = "g"; switch(x) case "k" disp("klein"); case "g" disp("gross"); otherwise disp("sonstiges") end
Ausgabe:
gross
Anmerkungen für C-Programmierer:
- in Octave darf zum Abschluß von case kein Doppelpunkt folgen (würde einen Syntaxfehler auslösen).
- ein break als Abschluß eines case-Blocks ist nicht erlaubt (würde in Octave einen parse error auslösen). break ist Schleifen vorbehalten. switch hat in Octave keinen "Durchfall" und ähnelt somit eher der Fortran-Anweisung select case.
Mehrere Fälle in einem case können wie nachfolgend behandelt werden:
x = "K"; switch(x) case {"k" "K"} disp("klein"); case {"g" "G"} disp("gross"); otherwise disp("sonstiges") end
Ausgabe:
klein
Schleifen
[Bearbeiten]Die WHILE-Schleife
[Bearbeiten]Die WHILE-Schleife ist kopfgesteuert. Sie funktioniert wie aus anderen Programmiersprachen bekannt.
In Pseudocode:
SOLANGE bedingung TRUE führe block aus ENDE
In Octave:
x = 0; while x <= 10 disp(x); x++; end
Ausgabe:
0 1 2 3 4 5 6 7 8 9 10
Die DO-UNTIL-Schleife
[Bearbeiten]Die DO-UNTIL-Schleife ist fußgesteuert. Beachte: Diese Schleife ist nicht äquivalent zu der aus anderen Programmiersprachen bekannten DO-WHILE-Schleife. DO-WHILE bedeutet "TUE SOLANGE", DO-UNTIL bedeutet "TUE BIS". Sie wird mindestens einmal ausgeführt.
Pseudocode:
TUE führe block aus BIS bedingung TRUE
Mittels Octave:
x = 0; do disp(x); x++; until(x >= 5)
Ausgabe:
0 1 2 3 4
Die FOR-Schleife
[Bearbeiten]for x = 0 : 2 : 10 disp(x); end
Ausgabe:
0 2 4 6 8 10
Der FOR-Schleifenkopf ist in Form einer Zahlenkolonne folgendermaßen aufgebaut:
for variable = startwert : schrittweite : endwert
Man beachte, dass Vektorisierung gegenüber einem Schleifendurchlauf eine erhebliche Zeiteinsparung bewirken kann (man siehe in der Octave-Dokumentation das Kapitel 19 "Vectorization and Faster Code Execution"). Folgendes Beispiel ist an genanntes Octave-Kapitel angelehnt. Zuerst wird eine Berechnung mittels Schleifendurchlauf durchgeführt und der Zeitbedarf ausgegeben. Dieser Zeitbedarf hängt natürlich auch von der verwendeten Hardware etc. ab.
Eingabe:
n = m = 500; a = b = eye(500); t1 = time(); for i = 1:n for j = 1:m c(i,j) = a(i,j) + b(i,j); endfor endfor t2 = time(); t_diff = t2-t1
Ausgabe:
t_diff = 3.7566
Der Zeitverbrauch beträgt hier also ca. 4 Sekunden. Im Gegensatz dazu
Eingabe:
a = b = eye(500); t1 = time(); c = a + b; t2 = time(); t_diff = t2-t1
Ausgabe:
t_diff = 1.5974e-05
ist der Zeitverbrauch hier sehr gering. Vektoren und Matrizen werden etwas später in diesem Text detailliert behandelt. Hier nur soviel: Mittels eye wird eine Einheitsmatrix kreiert.
Schleifen abbrechen
[Bearbeiten]Zum Abbrechen einer Schleife gibt es den Befehl "break".
for var = 0 : 1 : 100 disp (var); if var == 5 break; end end
Ausgabe:
0 1 2 3 4 5
"continue" setzt mit dem nächsten Schleifendurchlauf fort, z.B.
for var = 0 : 1 : 10 if var == 5 continue; end disp (var); end
Ausgabe:
0 1 2 3 4 6 7 8 9 10
Aufgaben
[Bearbeiten]- Berechnen Sie die Summe der ersten 10000 natürlichen Zahlen (bei 1 beginnend)
- in Form einer WHILE-Schleife
- in Form einer DO-UNTIL-Schleife
- in Form einer FOR-Schleife
- mittels sum-Befehl (siehe dazu auch die von Octave zur Verfügung gestellte Hilfefunktion).
- mittels gaußscher Summenformel ()
- Schreiben Sie für obige Alternativen Programme mit denen der Zeitbedarf der Schleifen, Befehle bzw. Formeln gemessen werden kann. Welche Alternativen sind aus Zeitgründen (minimale Laufzeit) empfehlenswert?
Grafiken zeichnen
[Bearbeiten]2D
[Bearbeiten]Graph einer Funktion
[Bearbeiten]Es soll die cosh-Funktion im Intervall gezeichnet werden. Der Programmcode lautet in der einfachsten Form:
x = -3 : .1: 3; y = cosh(x); plot(x,y); grid on;
Ausgabe:
Der Code ist quasi selbsterklärend. x läuft von -3 bis +3. y wird für jeden x-Wert per Formel ausgerechnet. "plot" ist der Zeichenbefehl. "grid on" schaltet ein Zeichengitter ein.
Die Schrittweite 0.1 wurde so gewählt, um einen ausreichend glatten Verlauf des Graphen zu gewährleisten. Das ist immer ein Kompromiss zwischen Berechnungszeit und Ansehnlichkeit. Testen Sie einfach ein paar verschiedene Werte, um ein Gefühl dafür zu zu bekommen.
Ein etwas komplexeres Beispiel ist folgendes
x = -3 : .1: 3; y = cosh(x) + 2.^x; plot(x,y); grid on;
Man beachte den Punkt bei 2.^x (2 hoch x). Vergisst man den Punkt, dann erhält man eine Fehlermeldung (ähnlich dieser):
error: for x^y, only square matrix arguments are permitted and one argument must be scalar. Use .^ for elementwise power. error: called from test1 at line 2 column 3
Ausgabe:
Der Funktionsgraph kann auch als Fläche eingefärbt werden:
x = -3 : .1: 3; y = cosh(x) + 2.^x; fill (x, y, "b");
Ausgabe:
Graphen mehrerer Funktionen und weiteres
[Bearbeiten]Mehrere Graphen lassen sich folgendermaßen in ein Fenster zeichnen:
x = -3 : .1: 3; y1 = cosh(x) + 2.^x; y2 = sin(x) .* cos(x); plot(x,y1, x,y2); title("Funktionsgraphen"); legend("cosh ...", "sin ..."); xlabel("x"); ylabel("y"); grid on;
Um die Linienstile etwas individueller zu gestalten, ist folgender Programmcode gedacht:
x = -3 : .1: 3; y1 = cosh(x) + 2.^x; y2 = sin(x) .* cos(x); plot(x,y1,"*r", x,y2,"ob"); title("Funktionsgraphen"); legend("cosh ...", "sin ..."); xlabel("x"); ylabel("y"); grid on;
Bei plot kann auch der Linienstil des jeweiligen Graphen angegeben werden, z.B. steht
* für Sternchenlinie o für Kreise in der Linie r für rot b für blau
Ein ähnliches Resultat liefert der Code:
x = -3 : .1: 3; y1 = cosh(x) + 2.^x; y2 = sin(x) .* cos(x); plot(x,y1, "Color", "red", "*", x,y2, "Color", "blue", "o"); title("Funktionsgraphen"); legend("cosh ...", "sin ..."); xlabel("x"); ylabel("y"); grid on;
Will man mehrere Graphen in ein Fenster zeichnen, aber nicht alles in einen plot-Befehl quetschen, so kann die "hold on"-Anweisung die Lösung des Problems sein:
%Lösche alle benutzerdefinierten Variablen aus der Symboltabelle clear; %Schließe alle Fenster close all; %Lösche Konsolenfenster und setze Cursor zurück clc; x = -3 : .1: 3; y1 = cosh(x) + 2.^x; y2 = sin(x) .* cos(x); plot(x,y1, "Color", "red"); hold on; plot(x,y2, "Color", "blue"); title("Funktionsgraphen"); legend("cosh ...", "sin ..."); xlabel("x"); ylabel("y"); grid on;
Bei diesem Program wurden auch einige Möglichkeiten (clear, close, clc) gezeigt, um das System aufzuräumen. Ein "hold off" würde natürlich die hold-Funktion wieder ausschalten.
Funktion in Parameterdarstellung
[Bearbeiten]Es soll die archimedische Spirale im Intervall gezeichnet werden.
clear; close all; clc; t = 0 : .1: 6*pi; x = t .* cos(t); y = t .* sin(t); plot(x,y); grid on;
Diese Darstellung erscheint verzerrt. Will man gleiche Achsenskalierungen, so kann man den axis-Befehl verwenden (axis muss nach plot erscheinen).
t = 0 : .1: 6*pi; x = t .* cos(t); y = t .* sin(t); plot(x,y); grid on; axis equal;
Strichstärke
[Bearbeiten]Für manche Zwecke ist es sinnvoll die Strichstärke des Graphen zu erhöhen. Dies kann über den Parameter "LineWidth" der plot-Funktion geschehen.
t = 0 : .1: 6*pi; x = t .* cos(t); y = t .* sin(t); plot(x,y, "LineWidth", 2); grid on; axis equal;
Ausgabe:
Beliebigen Text ausgeben
[Bearbeiten]x = -10:0.1:10; plot (x, sin (x), "LineWidth", 2); text (2.7, 0.8, "Das ist die sin-Funktion");
Ausgabe:
Logarithmische Achseneinteilung
[Bearbeiten]x = -3 : .1: 3; y = cosh(x) + 2.^x; % Halblogarithmische Darstellung semilogy(x,y); grid on;
Ausgabe:
Auch die x-Achse kann mit "semilogx" logarithmisch skaliert werden. Mit "loglog" werden beide Achsen logarithmisch skaliert.
Aufgaben
[Bearbeiten]- Zeichnen Sie die Strophoide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:
- Zeichnen Sie die verschlungene Hypozykloide . Das Ganze sollte in etwa so aussehen wie folgende Grafik:
- Testen Sie bei den obigen Übungsaufgaben verschiedene Linienstile und Farben (Hinweis: Siehe dazu auch die Octave-Hilfefunktion für den plot-Befehl).
- Testen Sie bei den obigen Übungsaufgaben verschiedene Werte für a, c, r und R.
- Erkunden Sie in der Octave-Hilfe den ezplot-Befehl.
3D
[Bearbeiten]Räumliche Kurven
[Bearbeiten]Mittels "plot3" lassen sich Raumkurven zeichnen.
t = 0 : .1 : 9*pi; x = cos(t); y = sin(t); z = 1.3 .^ t; plot3(x,y,z); grid on;
Flächen
[Bearbeiten]ezsurf
[Bearbeiten]Die wahrscheinlich einfachste Möglichkeit 3D-Flächen zu erzeugen, besteht in der Verwendung des ezsurf-Befehls. Beachten Sie beim folgenden Beispiel auch wieder den Punkt beim Multiplikationssymbol in der anonymen Funktion. Was eine anonyme Funktion ist, wird weiter hinten in diesem Text erklärt. Fürs Erste reicht es zu wissen, dass die Funktion f(x, y) jeweils im Intervall [0, 10] gezeichnet werden soll.
clear; close all; clc; clf; f = @(x, y) sin(x) + 3.*cos(y); ezsurf (f, [0, 10]);
Dieses Bild wurde mit der Octave-Version 5.2 erstellt. Es ist im Prinzip identisch zu jenen des folgenden Abschnitts, die mit der Version 3.0.3 erstellt wurden, nur die Farbschattierung ist anders. Ändern lässt sich diese Eigenschaft mit dem colormap-Befehl (siehe auch Octave-Hilfe):
clear; close all; clc; clf; colormap(hot); f = @(x, y) sin(x) + 3.*cos(y); ezsurf (f, [0, 10]);
surf und mesh
[Bearbeiten]Für das Zeichnen von Flächen existiert der surf-Befehl. Der meshgrid-Befehl kreiert ein Netz in der xy-Zeichenebene. Beachten Sie beim folgenden Beispiel auch wieder den Punkt beim Multiplikationssymbol der Formel für z.
x = 0 : .1 : 10; y = 0 : .1 : 10; [x_grid, y_grid] = meshgrid(x, y); z = sin(x_grid) + 3.*cos(y_grid); surf(x_grid, y_grid, z);
Auch ein Farbstreifen kann via "colorbar" zur Grafik hinzugefügt werden.
x = 0 : .1 : 10; y = 0 : .1 : 10; [x_grid, y_grid] = meshgrid(x, y); z = sin(x_grid) + 3.*cos(y_grid); surf(x_grid, y_grid, z); colorbar("East");
Das Ganze in Netzdarstellung läßt sich so programmieren:
x = 0 : .2 : 10; y = 0 : .2 : 10; [x_grid, y_grid] = meshgrid(x, y); z = sin(x_grid) + 3.*cos(y_grid); mesh(x_grid, y_grid, z);
Ausgabe:
Ellipsoide und Kegel
[Bearbeiten]Für das Zeichnen von Kugeln oder Ellipsoiden stellt Octave den "sphere"-Befehl bzw. den "ellipsoid"-Befehl zur Verfügung.
clear; close all; clc; % Ellipsoiden zeichnen [x, y, z] = sphere(30); surf(5*x, 4*y, 3*z); hold on; [x, y, z] = ellipsoid(5, 5, 5, 6, 3, 2, 30); surf(x, y, z); axis equal;
Für Zylinder und Kegel ist der "cylinder"-Befehl zuständig.
clear; close all; clc; % Kegel und Zylinder zeichnen [x, y, z] = cylinder([1 2], 100); surf(x, y, z*3); hold on; [x, y, z] = cylinder([0.5 0.5], 50); surf(x+3, y, z*2); axis equal;
Aufgaben
[Bearbeiten]- Zeichnen Sie die räumliche Kurve , , , . Das Ganze sollte etwa wie folgt aussehen:
- Zeichnen Sie die Fläche . Das Ganze sollte etwa wie folgt aussehen:
Weiteres
[Bearbeiten]subplot
[Bearbeiten]Zeichnen mit Untergrafiken: Hier wird z.B. ein Fenster mit drei Untergrafiken gezeichnet.
Eingabe:
t = 0 : .5 : 10; [x_grid, y_grid] = meshgrid(t, t); subplot(311); surf(x_grid, y_grid, sin(x_grid) + cos(y_grid) ); subplot(312); surf(x_grid, y_grid, sin(x_grid) + log(y_grid) ); subplot(313); surf(x_grid, y_grid, x_grid + cos(y_grid) );
Ausgabe:
Die dreistellige Ziffer beim subplot-Befehl bedeutet folgendes:
- Die erste Ziffer ist die Zeilenanzahl
- Die zweite Ziffer ist die Reihenanzahl und
- Die dritte Ziffer ist der Index.
Nun sei ein Beispiel mit 3x2-Untergrafiken angeführt.
clear; close all; clc; x = 0 : .1 : 10; subplot(321); plot(x, sin(x)); text(2, -0.5, "Index 1"); subplot(322); plot(x, tan(x)); text(2, 2, "Index 2"); subplot(323); plot(x, cosh(x) ); text(2, 3000, "Index 3"); subplot(324); plot(x, gamma(x) ) text(2, 100000, "Index 4"); subplot(325); plot(x, log(x) ); text(2, 0, "Index 5"); subplot(326); plot(x, exp(x) ); text(2, 10000, "Index 6");
Ausgabe:
Hier ist sehr gut zu sehen, in welcher Reihenfolge der Index läuft.
figure
[Bearbeiten]Zeichnen in verschiedene Fenster, z.B.
clear; close all; clc; x = 0 : .1 : 10; y = 0 : .1 : 10; [x_grid, y_grid] = meshgrid(x, y); figure(1) surf(x_grid, y_grid, sin(x_grid) + cos(y_grid)); figure(2) surf(x_grid, y_grid, sin(x_grid) + log(y_grid));
Ausgabe:
Linien zeichnen
[Bearbeiten]Zeichnen Sie eine Linie von der Koordinate [-15, 0] zu [15, 5]:
clear; close all; clc; x = line([-15 15], [0, 5], "Color", "black", "LineWidth", 2);
Ausgabe:
Man beachte, dass Octave nicht Punkte P1(x1, y1), P2(x2, y2) erwartet, sondern einen x-Vektor [x1 x2] und einen y-Vektor [y1 y2].
Ein allgemeines Viereck wird z.B. mit folgendem Befehl gezeichnet.
line([-15 15 10 -5, -15], [0, 5, 20, 15, 0], "LineWidth", 2);
Auch dreidimensionale Formen lassen sich mit dem line-Befehl zeichnen:
clear; close all; clc; line([-15 15 10 -5, -15], [0, 5, 20, 15, 0], [10, 20, 30, 40, 50], "LineWidth", 2);
Aufgaben
[Bearbeiten]- Zeichnen Sie mittels "subplot" die Funktionsgrafen in folgender Form in ein Fenster:
- in 2x2-Darstellung
- in 1x4-Darstellung.
- Zeichnen Sie die im obigen Beispiel angegebenen Funktionsgrafen mittels "figure" jeweils in ein eigenes Fenster.
Vektoren und Matrizen
[Bearbeiten]Vektoren
[Bearbeiten]Vektoren sollten jedem aus der Linearen Algebra bekannt sein.
Zeilen- und Spaltenvektoren
[Bearbeiten]% Ein Zeilenvektor v1 = [1, 2, 3] % Ein Spaltenvektor v2 = [6; 7; 8]
Ausgabe:
v1 = 1 2 3 v2 = 6 7 8
Alternative Schreibweisen:
% Ein Zeilenvektor v1 = [1 2 3] % Ein Spaltenvektor v2 = [6 7 8]
Die Ausgabe entspricht der obigen Darstellung.
Zugriff auf Vektorelemente
[Bearbeiten]Nachfolgend seien einige Zugriffsmöglichkeiten auf die einzelnen Vektorelemente erläutert.
Auf ein einzelnes Element kann via Index zugegriffen werden. Der Index startet bei 1:
v1 = [1 2 4 8 16]; v2 = v1(3)
Ausgabe:
v2 = 4
Mehrere Elemente werden folgendermaßen angesprochen:
v1 = [1 2 4 8 16]; v2 = v1(3:4)
Ausgabe:
v2 = 4 8
Liefere den Teilvektor von einem gegebenen Index bis zum letzten Element:
v1 = [1 2 4 8 16]; v2 = v1(3:end)
Ausgabe:
v2 = 4 8 16
Addition und Subtraktion von Vektoren
[Bearbeiten]v1 = [1, 2, 3]; v2 = [5, 7, 9]; res = v1 + v2 res = v1 - v2
Ausgabe:
res = 6 9 12 res = -4 -5 -6
Multiplikation mit Skalaren
[Bearbeiten]faktor = 3; v = [1, 2, 3]; res = faktor * v
Ausgabe:
res = 3 6 9
Skalarprodukt
[Bearbeiten]Das Skalarprodukt ist bekanntermaßen als definiert. In Octave sieht das so aus:
v1 = [1, 2, 3]; v2 = [5, 6, 7]; res = dot(v1, v2)
Ausgabe:
res = 38
Vektorprodukt
[Bearbeiten]v1 = [1, 2, 3]; v2 = [5, 6, 7]; res = cross(v1, v2)
Ausgabe:
res = -4 8 -4
Enger an die mathematische Darstellung lehnt sich folgender Code an. Die zu multiplizierenden Vektoren seien in Form von Spaltenvektoren gegeben.
Mathematisch:
Octave-Code:
a = [1 2 3]; b = [5 6 7]; res = cross(a, b)
Ausgabe:
res = -4 8 -4
Transponierter Vektor
[Bearbeiten]v1 = [1, 2, 3]; v2 = [5; 6; 7]; res1 = v1' res2 = v2'
Ausgabe:
res1 = 1 2 3 res2 = 5 6 7
Einige weitere Vektorfunktionen
[Bearbeiten]Beispiel:
% 1 + 2 + 3 v = [1 2 3]; sum(v)
Ausgabe:
ans = 6
Beispiel:
% 1 * 2 * 3 * 4 v = [1 2 3 4]; prod(v)
Ausgabe:
ans = 24
Beispiel:
% 1^2 + 2^2 + 3^2 v = [1 2 3]; sumsq (v)
Ausgabe:
ans = 14
Matrizen
[Bearbeiten]Gegeben sei folgende 2x3-Matrix .
Eingabe:
m = [1, 2, 3; 4, 5, 6]
Ausgabe:
m = 1 2 3 4 5 6
Alternativ und anschaulicher kann diese 2x3-Matrix auch so eingegeben werden:
m = [1 2 3 4 5 6]
Dies ist schon sehr nahe an der mathematischen Darstellungsweise.
Zugriff auf Matrizenelemente
[Bearbeiten]m = [1 2 3 4 5 6]; % Element aus Zeile 2 und Spalte 3 m(2,3)
Ausgabe:
ans = 6
Eine andere Zugriffsmöglichkeit ist diese:
m = [1 2 3 4 5 6]; % Auf das fünfte Element soll zugegriffen werden m(5)
Ausgabe:
ans = 3
Die Matrix wird also spaltenweise durchlaufen (nicht zeilenweise). Dies ist vielleicht auf den ersten Blick etwas ungewöhnlich, wird aber z.B. auch in Fortran so gehandhabt.
Auch Teilmatrizen können einfach gebildet werden:
m = [1 2 3 4 5 6]; m(2:end, 2:end)
Ausgabe:
ans = 5 6
Siehe zu diesem Thema auch etwas weiter hinten in diesem Text den Abschnitt "Teilmatrizen".
Addition und Subtraktion von Matrizen
[Bearbeiten]m1 = [1, 2, 3; 4, 5, 6]; m2 = [-4, -2, 0; 2, 4, 6]; m1 + m2 m1 - m2
Ausgabe:
ans = -3 0 3 6 9 12 ans = 5 4 3 2 1 0
Transponierte Matrix
[Bearbeiten]m = [1, 2, 3; 4, 5, 6]; m'
Ausgabe:
ans = 1 4 2 5 3 6
Rang einer Matrix
[Bearbeiten]Der Rang einer Matrix Rg(M) ist die maximale Anzahl der linear unabhängigen Zeilenvektoren (Spaltenvektoren).
m1 = [1, 2, 3; 4, 5, 6]; m2 = [1, 2; 2, 4]; rank(m1) rank(m2)
Ausgabe:
ans = 2 ans = 1
Regulär ist eine nxn-Matrix, wenn der Rg(M) = n. D.h. die erste Matrix m1 ist regulär, die zweite m2 singulär.
Inverse Matrix
[Bearbeiten]m1 = [1, 3; 0, -5 ]; m2 = [1, 2; 2, 4]; inv(m1) inv(m2)
Ausgabe:
ans = 1.00000 0.60000 0.00000 -0.20000 warning: matrix singular to machine precision warning: called from test1 at line 4 column 1 ans = Inf Inf Inf Inf
Die Matrix m2 in diesem Beispiel ist singulär (d.h. die Determinante ist 0). Determinanten werden etwas weiter unten in diesem Text behandelt. Inf steht für Infinity (= Unendlich).
Multiplikation von Matrizen (falksches Schema)
[Bearbeiten]m1 = [1, 3, 4; 0, -5, 1]; m2 = [1, 2; 2, 3; 0, 2]; m1 * m2
Ausgabe:
ans = 7 19 -10 -13
Determinante einer Matrix
[Bearbeiten]m1 = [1, 3; 0, -5 ]; m2 = [1, 2; 2, 4]; det(m1) det(m2)
Ausgabe:
ans = -5 ans = 0
m1 ist regulär, m2 ist singulär. Determinanten können nur von quadratischen Matrizen gebildet werden.
Teilmatrizen
[Bearbeiten]m = [1, 2, 3; 0, 5, 1]; % Die Matrix in einen Spaltenvektor umwandeln m1 = m(:) % Das Element aus der 1. Zeile und der 2. Spalte extrahieren m2 = m(1,2) % Erste Zeile extrahieren m3 = m(1, 1:3) m4 = m(1, :) % Zweite Spalte extrahieren m5 = m(1:2, 2) m6 = m(:, 2)
Ausgabe:
m1 = 1 0 2 5 3 1 m2 = 2 m3 = 1 2 3 m4 = 1 2 3 m5 = 2 5 m6 = 2 5
Einheitsmatrizen
[Bearbeiten]eye(3,2)
Ausgabe:
ans = 1 0 0 1 0 0
Nullmatrizen
[Bearbeiten]zeros(2,3)
Ausgabe:
ans = 0 0 0 0 0 0
Diagonalmatrizen
[Bearbeiten]diag([1, 2, 3])
Ausgabe:
ans = 1 0 0 0 2 0 0 0 3
Spur einer Matrix
[Bearbeiten]trace([1,2,3; 6,9, 0])
Ausgabe:
ans = 10
LR-Zerlegung einer Matrix
[Bearbeiten]Führen Sie die LR-Faktorisierung (LR ... links/rechts bzw. LU ... left/upper) einer Matrix m aus. l sei die linke Dreiecksmatrix, r die rechte Dreiecksmatrix und p die Permutationsmatrix
m = [1 0 5 -1 1 -2 0 0 3]; [l, r, p] = lu(m)
Ausgabe:
l = 1 0 0 -1 1 0 0 0 1 r = 1 0 5 0 1 3 0 0 3 p = 1 0 0 0 1 0 0 0 1
Eigenwerte
[Bearbeiten]a = [5 8 1 3]; % Eigenvektoren und Eigenwerte [ev, ew] = eig(a)
Ausgabe:
ev = 0.9701 -0.8944 0.2425 0.4472 ew = Diagonal Matrix 7 0 0 1
Die Eigenwerte sind hier und . Die Eigenvektoren sind [0.9701 0.2425] bzw. [-0.8944 0.4472]. Da das Gleichungssystem singulär ist, sind alle Lösungsvektoren Vielfache dieser Eigenvektoren.
Schwach besetzte Matrizen
[Bearbeiten]
Gegeben sei die schwach besetzte Matrix
m = [0 1 0 0 0 0 0 0 3 0 4 0 0 2 0 0 0 1 0 0 0 0 0 1 7]
Mittels dem sparse-Befehl kann man einfach die Elemente != 0 nach folgendem Schema eingeben.
sparse ([zeilenindizes] [spaltenindizes] [werte])
also in unserem Fall:
ms = sparse([1 2 3 3 4 5 5], [2 4 1 4 3 4 5], [1 3 4 2 1 1 7])
Ausgabe:
ms = Compressed Column Sparse (rows = 5, cols = 5, nnz = 7) (3, 1) -> 4 (1, 2) -> 1 (4, 3) -> 1 (2, 4) -> 3 (3, 4) -> 2 (5, 4) -> 1 (5, 5) -> 7
Die volle Matrix erhält man mit dem Befehl full:
m = full(ms)
Ausgabe:
m = 0 1 0 0 0 0 0 0 3 0 4 0 0 2 0 0 0 1 0 0 0 0 0 1 7
Grafisch anzeigen lassen kann man sich die Besetzung von Matrizen mit dem spy-Befehl:
spy(ms);
oder (für allgemeine Matrizen auch mittels)
spy(m);
Ausgabe:
Wirklich interessant ist der spy-Befehl für größere Matrizen, z.B. um die Bandstruktur zu visualisieren.
e = eye(200); es = sparse(e); % Auf sparse-Matrizen kann genauso zugegriffen werden wie auf normalen Matrizen es(100, 15) = 100; spy(es);
Ausgabe:
Matrizen mit Zufallswerten
[Bearbeiten]Insbesondere für Testzwecke kann es manchmal sinnvoll sein größere Matrizen mit Zufallswerten zu bilden. Dazu stellt Octave u.a. den rand-Befehl zur Verfügung.
m = rand(5, 6)
Ausgabe:
m = 0.86605 0.61108 0.71347 0.97119 0.52428 0.21993 0.74059 0.49062 0.56073 0.68592 0.74737 0.62680 0.20790 0.84874 0.36834 0.31102 0.25813 0.28933 0.84732 0.98777 0.91512 0.42240 0.87891 0.63757 0.76823 0.80367 0.24639 0.78208 0.77170 0.95281
Die Zufallszahlen liegen gleichverteilt zwischen 0 und 1 und werden nach dem Mersenne-Twister-Verfahren mit einer Periode von gebildet.
Andere Verfahren sind:
- randn: Normalverteilte Pseudozufallselemente mit Mittelwert=0 und Varianz=1
- rande: Exponentialverteilte Zufallselemente
- randg: Gammaverteilte Zufallselemente
- randp: Poissonverteilte Zufallselemente
Details dazu siehe in der Octave-Hilfefunktion.
Aufgaben
[Bearbeiten]- Berechnen Sie den Winkel zwischen den beiden Vektoren a = [1 2 0] und b = [2 1 1]. Hinweis: Siehe diesbezüglich auch im Oktave-Hilfesystem den Befehl "norm".
- Gegeben seien Vektoren a = [1 2 5], b = [0 0 -1] und c = [-1 -2 2]. Berechnen Sie das Spatprodukt aus diesen drei Vektoren.
- Multiplizieren Sie die beiden Matrizen A und B (mit Octave und zur Kontrolle händisch)
A = [0 0 1 1 2 1] B = [1 1 1 2 0 4]
- Ist die Matrix C regulär? Wenn ja, dann bilden Sie die inverse Matrix.
C = [-1 0 0 -4 2 0 1 5 7 6 2 0 3 0 2 6]
- Ist die Matrix D regulär? Wenn ja, dann bilden Sie die inverse Matrix.
D = [2 1 0 0 0 0 2 1 0 0 0 2 1 1 0 0]
- Berechnen Sie die Konditionszahl der folgenden Matrix. Hinweis: Siehe diesbezüglich im Oktave-Hilfesystem den Befehl cond
[3 4 -5 6 0 3 1 1 2]
- Berechnen Sie die Eigenwerte und Eigenvektoren der folgenden Matrix
[6 -3 4 0 0 7 -1 1 0 10 -3 -2 0 1 -2 1]
Komplexe Zahlen
[Bearbeiten]Die imaginäre Einheit wird in Octave durch den Buchstaben i, j, I oder J symbolisiert. Darstellen kann man eine komplexe Zahl bekannterweise in mehreren Formen:
- Kartesische Darstellung
- Polardarstellungen
Die konjugiert komplexe Zahl ist
Mit komplexen Zahlen rechnen
[Bearbeiten]z1 = 2 + 5i; % kartesische Darstellung z2 = 3 * exp(3j); % Polardarstellung % Addition res = z1 + z2; disp("z1 + z2 = "); disp(res); % Multiplikation res = z1 * z2; disp("z1 * z2 = "); disp(res); % Realteil res = real(z2); disp("Realteil von z2 = "); disp(res); % Imaginärteil res = imag(z2); disp("Imaginaerteil von z2 = "); disp(res); % Betrag res = abs(z1); disp("Betrag von z1 = "); disp(res); % Argument res = angle(z1); disp("Argument von z1 = "); disp(res); % Konjugiert komplexe Zahl res = conj(z1); disp("Konjugiert komplexe Zahl von z1 = "); disp(res);
Ausgabe:
z1 + z2 = -0.96998 + 5.42336i z1 * z2 = -8.0568 - 14.0032i Realteil von z2 = -2.9700 Imaginaerteil von z2 = 0.42336 Betrag von z1 = 5.3852 Argument von z1 = 1.1903 Konjugiert komplexe Zahl von z1 = 2 - 5i
Die gaußsche Zahlenebene
[Bearbeiten]clear; close all; clc; z1 = 3 + 5i; z2 = 5 * exp(0.5i); hold on; plot(z1, "*"); compass(z1); plot(z2, "o"); compass(z2); grid on;
Aufgaben
[Bearbeiten]- Berechnen Sie die Quadratwurzel der komplexen Zahl .
- Verwandeln Sie folgende Zahlen in die Polarkoordinatendarstellung: und
- Verwandeln Sie folgende Zahlen in die Normaldarstellung: und
- Zeichnen Sie die Zahl in der gaußschen Zahlenebene als Zeiger.
Funktionen
[Bearbeiten]Um Programme zu strukturieren und einfacher zu gestalten können Programmteile in Funktionen ausgelagert werden. Eingebaute Funktionen haben wir schon kennengelernt (z.B. die Sinus-Funktion sin). Nun wollen wir sehen, wie man selbst solche Funktionen schreiben kann.
Eine einfache Funktion schreiben
[Bearbeiten]Datei addiere.m:
function res = addiere(a, b) % Addiere zwei Zahlen a + b res = a + b; end
Datei test1.m:
addiere(10, 15)
Ausgabe:
ans = 25
- Jede Funktion sollte in einer eigenen m-Datei stehen.
- Der Dateiname sollte mit dem Funktionsnamen (natürlich ohne Dateiendung .m) übereinstimmen.
- Der Kommentar unter dem Funktionskopf wird als Hilfstext angezeigt, wenn die help-Funktion (hier "help addiere") aufgerufen wird.
Inline-Funktionen
[Bearbeiten]Kurze Funktionen können auch als Inline-Funktionen geschrieben werden.
addiere = inline("a + b"); x = 5; y = 10; z = addiere(x, y)
Oder in diesem Fall noch kürzer
addiere = inline("a + b"); z = addiere(5, 10)
Ausgabe:
z = 15
Bei neueren Octave-Versionen kann bei der Verwendung von Inline-Funktionen die Warnung
warning: inline is obsolete; use anonymous functions instead
erscheinen. Ein Blick in die Hilfe-Funktion
help inline
zeigt das selbe Ergebnis. Es sollen also anonyme Funktionen (siehe etwas weiter unten in diesem Text) anstelle von Inline-Funktionen verwendet werden.
Funktionsstring
[Bearbeiten]addiere = "a + b"; a = 5; b = 10; z = eval(addiere)
Ausgabe:
z = 15
Anonyme Funktionen
[Bearbeiten]
addiere = @(a, b) a + b; x = 10; y = 20; z = addiere(x, y)
oder kürzer
addiere = @(a, b) a + b; z = addiere(10, 20)
Ausgabe:
z = 30
Nullstellen von Funktionen bestimmen
[Bearbeiten]sinh2 = @(x) sinh(x) + 2; z = fzero(sinh2, 1)
Ausgabe:
z = -1.4436
Zur Kontrolle soll hier der Graph der Funktion dargestellt werden
clear; close all; clc; sinh2 = @(x) sinh(x) + 2; x = -2 : 0.1 : 0; y = sinh2(x); z = fzero(sinh2, 1) plot(x, y); hold on; plot(z, 0, "o", "Color", "red", "LineWidth", 2); text (-1.8, 0.8, "Nullstelle"); line([z -1.7], [0, .7], "Color", "black"); grid on;
Ausgabe:
Weiter unten im Text wird die ähnliche Funktion "fsolve" beschrieben. "fzero" benutzt zwei verschiedene Funktionen zur Problemlösung, darunter eben auch "fsolve".
Für die Nullstellenbestimmung von Polynomen gibt es die Funktion "roots". Näheres dazu folgt im nächsten Kapitel.
Globale Variablen
[Bearbeiten]Datei addiere.m:
function res = addiere() global a b; res = a + b; end
Datei test1.m:
clear; close all; clc; global a b; a = 5; b = 3; addiere()
Ausgabe:
ans = 8
Aufgaben
[Bearbeiten]- Schreiben Sie eine Funktion "ellipse", welche eine Ellipse am Bildschirm darstellt. Zur Erinnerung: Die Parameterdarstellung der Ellipse lautet , Funktionsargumente seien a und b.
- Schreiben Sie
- als normale Funktion
- als Funktionsstring
- als Inlinefunktion
- als anonyme Funktion
- stellen Sie diese Funktion grafisch am Bildschirm dar.
Polynome
[Bearbeiten]Einzelne Polynomwerte berechnen
[Bearbeiten]% y = 2*x^3 + 5*x^2 + 4 für x = 2 berechnen p = [2, 5, 0, 4]; polyval(p, 2)
Ausgabe:
ans = 40
Polynome zeichnen
[Bearbeiten]% y = 2*x^3 - 5*x^2 + 4 für das Intervall -5 <= x <= 5 grafisch darstellen x = -5 : .1 : 5; p = [2, 5, 0, 4]; y = polyval(p, x); plot(x,y); grid on;
Ausgabe:
Nullstellen bestimmen
[Bearbeiten]Für Polynome existiert die Funktion "roots" zur Nullstellenbestimmung.
% Nullstellen für y = 2*x^3 - 5*x^2 + 4 bestimmen p = [2, 5, 0, 4]; r = roots(p)
Ausgabe:
r = -2.76214 + 0.00000i 0.13107 + 0.84077i 0.13107 - 0.84077i
Dieses Polynom hat nur eine reelle Nullstelle. Diese liegt, wie am obigen Grafen zu ersehen ist, in der Nähe von -2.762. Die beiden anderen Nullstellen sind konjugiert komplex zueinander (wie es auch sein sollte).
Aufgaben
[Bearbeiten]- Berechnen Sie den Wert für x = 3 des Polynoms .
- Berechnen Sie die Nullstellen von .
- Zeichnen Sie das Polynom im Intervall .
Lineare Gleichungssysteme
[Bearbeiten]Sei ein lineares Gleichungssystem. sei die Koeffizientenmatrix, der Lösungsvektor und ein bekannter Vektor.
Einfache Berechnung mittels Gauß-Verfahren
[Bearbeiten]
Beispiel:
A = [5 1 0 2]; b = [1 2]; x = A \ b
Ausgabe:
x = 0 1
Das gmres-Verfahren
[Bearbeiten]gmres steht für Generalized Minimal Residual.
A = [5 1 0 2]; b = [1 2]; x = gmres(A, b)
Ausgabe:
gmres converged at iteration 2 to a solution with relative residual 2.22045e-16 x = -1.6653e-16 1.0000e+00
Das Ergebnis weicht etwas vom gaußschen Verfahren ab, ist aber trotzdem im Rahmen der Näherung korrekt.
Weiters kennt Octave noch andere iterative Verfahren, z.B. cgs (Conjugate Gradient Squared) oder bicgstab (Bi-Conjugate Gradient Stabilized). Näheres zu diesen Verfahren siehe in der weiterführenden Literatur (z.B. bei Meister: Numerik linearer Gleichungssysteme, Vieweg+Teubner, 2011)
Aufgabe
[Bearbeiten]- Lösen Sie folgendes Gleichungssystem mittels Octave (und zur Kontrolle auch händisch):
5x + 6y - 2z = 12 3x - y - 3z = 6 2x + 2y + 4z = 5
Nichtlineare Gleichungssysteme
[Bearbeiten]fsolve und fzero
[Bearbeiten]Löse eine beliebige Gleichung f(x) = 0, z.B. :
f = @(x) x^2 - 5*cos(x) - 10; xstart = 1; [x, fval, info] = fsolve(f, xstart)
Ausgabe:
x = 2.4681 fval = -1.7764e-015 info = 1
- x ist eine Nullstelle in der Nähe vom Startwert xstart.
- fval ist die Abweichung, den f bei x aufweist.
- info ist ein "Fehlercode": 1 bedeutet, dass der relative Fehler in der spezifizierten Toleranz liegt (wie es sein soll). 3 würde bedeuten, dass der Algorithmus nicht konvergiert (z.B. weil keine Nullstelle existiert).
Zur Kontrolle plotten wir den Funktionsgraphen:
x = - 1 : .1 : 3; y = x.^2 - 5.*cos(x) - 10; plot(x,y, "LineWidth", 2); grid on;
Ausgabe:
Und siehe da, die gesuchte Nullstelle liegt wie berechnet bei einem Wert nahe 2,5. Die Funktion hat noch eine zweite Nullstelle, wie in der folgenden Abbildung zu erkennen ist.
Diese zweite Nullstelle erhalten wir, wenn der Startwert in der Nähe dieser zweiten Nullstelle liegt, also z.B. bei -1. Ändern Sie einfach den entsprechenden Startwert im obigen Programmcode, und das Programm sollte die Nullstelle in der Nähe von -2.5 liefern.
Auch die Funktion fzero kann zur Lösung einer nichtlinearen Gleichung verwendet werden. Die Hilfe-Funktion von Octave empfiehlt dies sogar eindringlich für den Fall einer nichtlinearen Gleichung in einer Variablen. Für das gleiche Beispiel wie oben kann der Programmcode folgendermaßen aussehen:
Eingabe:
f = @(x) x^2 - 5*cos(x) - 10; [x0, y0] = fzero (f, [0, 3])
Ausgabe:
x0 = 2.4681 y0 = -1.2434e-14
Gleichungssysteme
[Bearbeiten]Folgende Aufgabe ist dem Buch "Knorrenschild: Numerische Mathematik, Hanser, 2017, Seite 72" entnommen. Zu lösen ist das nichtlineare Gleichungssystem
Lösung:
f.m:
function y = f(x) y(1) = 2*x(1) + 4*x(2); y(2) = 4*x(1) + 8*x(2)^3; end
test1.m:
clear; close all; clc; [x, fval, info] = fsolve (@f, [0, 1]) [x, fval, info] = fsolve (@f, [0, -1]) [x, fval, info] = fsolve (@f, [0, 0])
Ausgabe:
x = -2 1 fval = 0 7.4930e-09 info = 1 x = 2 -1 fval = 0 -7.4930e-09 info = 1 x = 0 0 fval = 0 0 info = 1
Aufgaben
[Bearbeiten]- Bestimmen Sie die Nullstellen von . Plotten Sie den Grafen.
- Bestimmen Sie die Nullstelle von . Plotten Sie den Grafen.
- Lösen Sie das folgende Gleichungssystem (und stellen Sie das Ganze grafisch am Bildschirm dar):
Interpolation
[Bearbeiten]Eindimensionale Interpolation
[Bearbeiten]
Bezüglich eindimensionaler Interpolation sei auf die Octave-Dokumentation und Hilfefunktion zum Befehl " interp1" verwiesen. Dort findet sich auch ein Programmbeispiel, das als Grundlage des folgenden Plots dient:
Mehrdimensionale Interpolation
[Bearbeiten]Bezüglich mehrdimensionaler Interpolation siehe die Hilfefunktion zu "interp2", "interp3" und "interpn".
Aufgabe
[Bearbeiten]- Gegeben seinen die fünf Stützpunkte p1 = [1, 0], p2 = [2, -5], p3 = [3, 2], p4 = [4, 7], p5 = [5, 6]. Legen Sie eine Funktion (die Interpolierende) durch diese Stützpunkte. Eine Lösungsmöglichkeit:
xp = [1 2 3 4 5]; yp = [0, -5, 2, 7, 6]; xf = 1 : .1 : 5; spl = interp1(xp, yp, xf, "spline"); pch = interp1(xp, yp, xf, "pchip"); plot(xp, yp, "or", "LineWidth", 2, xf, spl, "LineWidth", 2, ... xf, pch, "LineWidth", 2); legend("stuetzpunkte", "spline", "pchip", "location", "southeast");
Differenzialrechnung
[Bearbeiten]Polynome differenzieren
[Bearbeiten]Es soll das Polynom differenziert werden.
% Differenzieren des Polynoms y = 2*x^3 - 5*x^2 + 7 p = [2, -5, 0, 7]; polyder(p)
Ausgabe:
ans = 6 -10 0
D.h. also, die Ableitung von ist .
Sonstige Funktionen differenzieren
[Bearbeiten]Als Beispiel differenzieren wir und stellen das Ganze grafisch dar.
clear; close all; clc; x = 0 : 0.01 : 10; y = 5 .* x .* sin(x); y_strich = diff(y) / 0.01; plot(x, y, "Color", "red", "LineWidth", 2); hold on; plot(x(1:length(x)-1), y_strich, "Color", "blue", "LineWidth", 2); legend("y", "y'"); grid on;
Ausgabe:
diff(y) ist der Vektor aus den Differenzen y(2)-y(1), ..., y(n)-y(n-1). Für die genaue Arbeitsweise der diff-Funktion siehe "help diff".
Aufgaben
[Bearbeiten]- Differenzieren Sie das Polynom .
- Differenzieren Sie die Funktion und stellen Sie y, sowie y' grafisch am Bildschirm dar.
- Differenzieren Sie die Funktion und stellen Sie y, sowie y' grafisch am Bildschirm dar.
Integralrechnung
[Bearbeiten]Polynome integrieren
[Bearbeiten]Berechnen Sie das unbestimmte Integral von
p = [2, -7, 0, 7]; p_int = polyint(p)
Ausgabe:
p_int = 0.50000 -2.33333 0.00000 7.00000 0.00000
Das Ergebnis lautet also (auf die Integrationskonstante C darf nicht vergessen werden!).
Gauß-Quadratur
[Bearbeiten]
Berechnen Sie das Integral mittels Gauß-Quadratur.
Datei f.m:
function y = f(x) y = x^2; end
Datei test1.m:
[v, ier, nfun, err] = quad ("f", 0, 3)
Ausgabe:
v = 9.0000 ier = 0 nfun = 21 err = 9.9920e-014
Erläuterung zur Ausgabe:
- v ... Resultat der Integration
- ier ... integer error code
- nfun ... Anzahl der Funktionsaufrufe
- err ... Fehler in der Lösung
Quadratur mittels adaptiver Lobatto-Regel
[Bearbeiten]Berechnen Sie diesmal das Integral mittels Lobatto-Quadratur.
f = inline("x.^2"); v = quadl (f, 0, 3)
Ausgabe:
v = 9
Wie weiter oben bereits angesprochen kann bei der Ausgabe eine Warnung erfolgen. Inline-Funktionen sind inzwischen als obsolet erklärt und es sollen stattdessen anonyme Funktionen verwendet werden.
Zwecks Übung sei nachfolgend nochmals dieses Beispiel berechnet. Diesmal wird aber eine anonyme Funktion verwendet.
v = quadl (@(x) x.^2, 0, 3)
Aufgaben
[Bearbeiten]- Integrieren Sie das Polynom .
- Integrieren Sie die Funktion von -5 bis 5.
- Integrieren Sie die Funktion von 0 bis 4. Verwenden Sie hierzu die Simpsonregel (siehe dazu in der Hilfefunktion den Befehl "quadv").
Gewöhnliche Differenzialgleichungen
[Bearbeiten]ode23, ode45 und lsode
[Bearbeiten]Für die Lösung von Differenzialgleichungen stehen die Funktionen
- ode23
bzw.
- ode45
zur Verfügung. Diese Funktionen implementieren das Runge-Kutta-Verfahren. "ode" steht für "Ordinary Differential Equation" (also auf Deutsch für "Gewöhnliche Differentialgleichung"). Die Zahlen bei ode23 oder ode45 stehen für die Ordnung.
Beispiel :
clear; close all; clc; [x, y] = ode45(@(x,y) (x^2+y^3), [0 1], 0); plot(x, y, "LineWidth", 2);
Ausgabe:
Bezüglich der genauen Funktionsweise von "ode45" (oder "ode23") siehe die Octave-Hilfe.
Auch die Funktion "lsode" steht zur Lösung von ODEs zur Verfügung.
Beispiel :
clear; close all; clc; t = 0 : .1 : 5; [y2, istate, msg] = lsode(@(x,y) (x + y), 1, t); istate msg plot(t, y2);
Ausgabe:
istate = 2 msg = successful exit
Bezüglich der genauen Funktionsweise von "lsode" siehe die Octave-Hilfe.
Aufgaben
[Bearbeiten]- Lösen Sie die Differenzialgleichung mit Octave. Kontrollieren Sie das Ergebnis, indem Sie die DGl händisch lösen.
- Lösen Sie die Differenzialgleichung . Kontrollieren Sie das Ergebnis, indem Sie die DGl händisch lösen.
- Lösen Sie die Differenzialgleichung .
Die Fast-Fourier-Transformation
[Bearbeiten]
Für die Funktion "fft" siehe das Octave-Hilfesystem.
Mengenrechnung
[Bearbeiten]Vereinigungsmenge
[Bearbeiten]v1 = [1 2 3 4]; v2 = [2 4 6]; union(v1, v2)
Ausgabe:
ans = 1 2 3 4 6
Schnittmenge
[Bearbeiten]v1 = [1 2 3 4]; v2 = [2 4 6]; intersect(v1, v2)
Ausgabe:
ans = 2 4
Logik
[Bearbeiten]Logische Operatoren werden oft benötigt, z.B. bei Schleifen und Verzweigungen.
Octave kennt die logischen Operatoren or, and, not
und xor
. Als Beispiel sei die Wahrheitstabelle für den Operator or
dargestellt.
A B A or B -------------------- true true true true false true false true true false false false
In Octave kann das so ausgedrückt werden:
or( true, true ) or( true, false ) or( false, true ) or( false, false )
Ausgabe:
ans = 1 ans = 1 ans = 1 ans = 0
Zahlen ungleich 0 stehen für true, 0 für false. Z.B.:
or( 22, 0)
Ausgabe:
ans = 1
Äquivalent zu or
ist der Operator |
:
22 | 0
Ausgabe:
ans = 1
Zwecks näheren Informationen zu den Operatoren and (&, &&), not (~, !)
und xor
bemühe man Octaves Help-Funktion.
Bitweise logische Funktionen kennt Octave auch, so kann man z.B. zwei Zahlen mit dem bitweisen OR-Operator verknüpfen:
0b1100101 0b0110001 --------- 0b1110101
Oder in Dezimalzahlen:
101 49 --- 117
In Octave:
bitor( 0b1100101, 0b0110001 ) dec2bin( ans )
Ausgabe:
ans = 117 ans = 1110101
Zu bitand, bitxor
usw. siehe die Octave-Hilfe-Funktion.
Stochastik
[Bearbeiten]Deskriptive Statistik
[Bearbeiten]Lageparameter
[Bearbeiten]Arithmetischer Mittelwert:
vec = [1 2 3 4 5 12 13]; mw = mean(vec)
Ausgabe:
mw = 5.7143
Der Median oder Zentralwert läßt sich folgendermaßen berechnen:
vec = [1 2 3 4 5 12 13]; median(vec)
Ausgabe:
ans = 4
Der Modus oder häufigste Wert läßt sich mittels "mode"-Funktion eruieren:
vec = [1 2 1 3 5 1 2 7]; [m, f, c] = mode (vec); disp(m); disp(f); disp(c);
Ausgabe:
1 3 { [1,1] = 1 }
m (erste Zeile der Ausgabe) ist der Modus. f (zweite Zeile) ist die Häufigkeit. Näheres dazu siehe im Octave-Hilfesystem.
Streuungsparameter
[Bearbeiten]Varianz:
vec = [1 2 3 1 1 6 7]; v = var(vec)
Ausgabe:
v = 6.3333
Standardabweichung:
vec = [1 2 3 1 1 6 7]; s = std(vec)
Ausgabe:
s = 2.5166
Grafiken erzeugen
[Bearbeiten]Histogramme:
v = [1 1 2 3 1 6 7 6 1 1 1 2]; hist(v, max(v));
Ausgabe:
Balkendiagramme:
v = [1 1 2 3 1 6 7 6]; bar(v);
Ausgabe:
Treppendiagramm:
v = [1 1 2 3 1 6 7 6]; stairs(v);
Ausgabe:
Stabdiagramm:
v = [1 1 2 3 1 6 7 6]; stem(v);
Ausgabe:
Aufgaben
[Bearbeiten]Gegeben sei folgende Datentabelle mit den Werten:
v1 = [3 4 1 1 7 2 1 9 2 5 9 7 2 2 9 2 2 1 2 8] v2 = [1 1 0 2 3 4 1 2 7 0 2 1 5 5 5 4 5 2 5 0]
- Berechnen Sie die Lageparameter und Streuungsparameter des Vektors v1.
- Berechnen Sie Kovarianz und Korrelationskoeffizient der beiden zugeordneten Vektoren v1 und v2.
- Zeichnen Sie das Histogramm des Vektors v1.
Wahrscheinlichkeitsrechnung
[Bearbeiten]Kombinatorik
[Bearbeiten]Der Binomialkoeffizient:
In Octave z.B.:
n = 30; k = 4; n_ueber_k = nchoosek (n, k)
Ausgabe:
n_ueber_k = 27405
Permutationen sind die verschiedenen Anordnungsmöglichkeiten mit der Anzahl n! = n * (n-1) * ... * 2 * 1.
Beispiel:
v = [1, 2, 3]; p = perms(v)
Ausgabe:
p = 1 2 3 2 1 3 1 3 2 2 3 1 3 1 2 3 2 1
n! (n-Fakultät) selbst kann so berechnet werden:
% 10! n = 10; factorial (n)
Ausgabe:
ans = 3628800
Verteilungen
[Bearbeiten]Octave kennt eine ganze Reihe von Dichte- und Verteilungsfunktionen und zwar
- Probability Density Functions (PDF, Dichtefunktionen)
- Cumulative Distribution Functions (CDF, Verteilungsfunktionen)
Z.B.:
- Binomialverteilung:
- binopdf
- binocdf
- Hypergeometrische Verteilung:
- hygepdf
- hygecdf
- Normalverteilung:
- normpdf
- normcdf
- Studentverteilung:
- tpdf
- tcdf
- Weibullverteilung:
- wblpdf
- wblcdf
Ein Codebeispiel zur Binomialverteilung:
clear; close all; clc; x = 0 : 1 : 10; n = 10; p = 0.1; b1 = binopdf (x, n, p); b2 = binocdf (x, n, p); subplot(221); bar(x, b1); title("binopdf"); text(1, 0.1, "n=10; p=0.1"); subplot(222); bar(x, b2); title("binocdf"); text(1, 0.5, "n=10; p=0.1"); n = 10; p = 0.5; b1 = binopdf (x, n, p); b2 = binocdf (x, n, p); subplot(223); bar(x, b1); text(1, 0.1, "n=10; p=0.5"); subplot(224); bar(x, b2); text(1, 0.1, "n=10; p=0.5");
Ausgabe:
Möglicherweise erhalten Sie bei diesem Beispiel eine Fehlermeldung in der Form
error: 'binopdf' undefined near line 8, column 6 The 'binopdf' function belongs to the statistics package from Octave Forge which you have installed but not loaded. To load the package, run 'pkg load statistics' from the Octave prompt.
Laden Sie einfach das Paket für die Statistikfunktionen, wie in der Fehlermeldung beschrieben.
Ein Codebeispiel zur Normalverteilung:
clear; close all; clc; x = -4 : .1 : 4; b1 = normpdf(x); b2 = normcdf(x); subplot(121); plot(x, b1); title("normpdf"); grid on; subplot(122); plot(x, b2); title("normcdf"); grid on;
Ausgabe:
Zufallszahlengeneratoren
[Bearbeiten]Octave kann Zufallszahlen aus einer großen Anzahl von Verteilungen generieren, z.B.
- Chi-Quadrat-Verteilung: chi2rnd
- Log-Normal-Verteilung: lognrnd
- Normalverteilung: normrnd
Codebeispiel:
mean = 0; standardabweichung = 1; zufallszahl = normrnd (mean, standardabweichung)
Ausgabe (gibt eine Zufallszahl rund um den Mittelwert 0 aus), z.B.
zufallszahl = 1.0451
Auch Zufallsvektoren (oder Zufallsmatrizen) können erstellt werden:
mean = [0 0 0 0 0]; standardabweichung = 1; zufallsvektor = normrnd (mean, standardabweichung)
Ausgabe, z.B.:
zufallsvektor = 1.47108 -0.51280 0.52726 0.31730 -1.04422
Einfache Benutzeroberflächen erstellen
[Bearbeiten]Input
[Bearbeiten]fflush (stdout); x = input("Gib eine Zahl ein: "); disp(2 * x);
Ein-/Ausgabe:
Gib eine Zahl ein: 12 24
Der "fflush"-Befehl sollte immer vor dem Aufruf des input-Befehls aufgerufen werden. Näheres zu "fflush" siehe im Octave-Hilfesystem.
Diverse einfache vorgefertigte Dialoge
[Bearbeiten]Fehlermeldung:
errordlg("Fehlermeldung");
Warnung:
warndlg("Warnung");
Hilfedialog:
helpdlg
Abfragedialog:
button = questdlg ("Frage")
Eingabedialog:
in = inputdlg("Eingabe")
Messagebox:
h = msgbox ("Eine Mitteilung!");
Komplexere vorgefertigte Dialogboxen
[Bearbeiten]Menübox
[Bearbeiten]auswahl = menu("Auswahl", "Affe", "Elefant", "Loewe", "Sonstiges"); switch(auswahl) case 1 disp "Affe quietscht" case 2 disp "Elefant trompetet" case 3 disp "Loewe bruellt" otherwise disp "Sonstiges" end
Ausgabe:
Es werde beispielsweise die Nummer 2 gewählt.
Ausgabe:
Elefant trompetet
Dialogliste
[Bearbeiten]clear; close all; clc; opt = {"Eins", "Zwei", "Drei"}; [sel, ok] = listdlg ("ListString", opt, "SelectionMode", "Multiple"); if (ok == 1) for i = 1 : numel(sel) disp(opt{sel(i)}); end else disp("Cancel"); end
Es werden beispielsweise alle Optionen ausgewählt.
Ausgabe:
Eins Zwei Drei
Fortschrittsbalken
[Bearbeiten]h = waitbar ([0.5])
Datei- und Verzeichnisdialoge
[Bearbeiten]Dateidialog:
[fname, fpath, fltidx] = uigetfile ()
Ähnlich sind die Befehle "uiputfile" und "uigetdir". Dazu sei auf die Octave-Hilfe verwiesen.
Eigene Dialoge kreieren
[Bearbeiten]Dieses Thema sei hier nicht näher vertieft. Wer mehr dazu wissen will, sei auf die Octave-Dokumentation verwiesen. Insbesondere siehe auch
- dialog
- uicontrol
- uipanel
- uibuttongroup
- uitable
- uimenu
- uitoolbar
Fehlerhandling mit try/catch
[Bearbeiten]Die try/catch-Anweisung entspricht weitgehend jener, die aus höheren Programmiersprachen wie C++ oder Java bekannt sind. Aufgebaut ist diese Anweisungsfolge so:
try BODY catch CLEANUP end
Beispiel:
clear; close all; clc; try a = 10 / "zahl"; disp(a); disp("Weiter im try-Block"); catch disp("Catch: Kann nicht durch einen String dividieren"); end
Ausgabe:
Catch: Kann nicht durch einen String dividieren
Sinnvoll ist die try/catch-Folge, wenn z.B. auch in einem Fehlerfall Dateien wieder geschlossen werden sollen.
Ein- und Ausgabe
[Bearbeiten]Formatierte Ausgabe am Bildschirm, formatiertes Lesen von der Tastatur
[Bearbeiten]Folgendes Beispiel ist der Octave-Hilfe (von Octave 3.0.3) entnommen:
pct = 37; filename = "foo.txt"; printf ("Processed %d%% of `%s'.\nPlease be patient.\n", pct, filename);
Ausgabe:
Processed 37% of `foo.txt'. Please be patient.
"printf" gibt einen formatierten String am Bildschirm (genauer in den Stream stdout) aus. Wie man sieht, orientiert sich das Format an der Programmiersprache C.
Für das formatierte Lesen vom Stream stdin (normalerweise also von der Tastatur) steht das Pendant "scanf" bereit.
Von einem String lesen bzw. in einen String schreiben
[Bearbeiten]Bezüglich der Funktionen
- sprintf
und
- sscanf
sei auf die Octave-Hilfefunktion verwiesen.
Lesen und Schreiben von einer Datei
[Bearbeiten]Datei schreiben
[Bearbeiten]% Datei c:\tmp\datei.test zum Schreiben öffnen datei = fopen ("c:/tmp/datei.test", "w"); % Etwas in die Datei schreiben fprintf(datei, "Hallo, Welt!"); % Datei schließen fclose(datei);
Datei lesen
[Bearbeiten]% Datei c:\tmp\datei.test zum Lesen öffnen datei = fopen ("c:/tmp/datei.test", "r"); % Etwas aus der Datei lesen [string] = fscanf(datei, "%s"); disp(string); % Datei schließen fclose(datei);
Ausgabe:
Hallo,Welt!
Dateiende prüfen
[Bearbeiten]Mittels des Befehls
feof(FID);
kann das Dateiende geprüft werden. Wenn die EOF-Bedingung zutrifft, dann wird 1 zurückgegeben, wenn nicht dann 0. Ein Beispiel folgt später als Lösung einer Aufgabe.
warning und error
[Bearbeiten]Eine Warnung kann man am stderr-Stream ausgeben. Die warning-Funktion entspricht ansonsten der printf-Funktion. Nach Ausgabe der Warnung wird das Programm normal fortgesetzt.
m = [1 2 3 6]; if(det(m) == 0) warning("Matrix ist singulaer"); end disp("Weiter geht's");
Ausgabe:
warning: Matrix ist singulaer warning: called from test1 at line 5 column 3 Weiter geht's
Schärfer ist der error-Befehl. Die Fehlermeldung wird am stderr-Stream ausgegeben. Vom Format her entspricht diese Funktion dem printf-Befehl. Nach Ausgabe der Fehlermeldung wird das Programm beendet.
m = [1 2 3 6]; if(det(m) == 0) error("Matrix ist singulaer"); end disp("Weiter geht's");
Ausgabe:
error: Matrix ist singulaer error: called from test1 at line 5 column 3
Aufgaben
[Bearbeiten]- Schreiben Sie ein Programm, das die Zahlen 1 bis 10 zeilenweise in eine Datei ausgibt.
- Lesen Sie diese Zeilen wieder von der Datei ein und geben Sie sie am Bildschirm aus.
- Gegeben sei eine Datei. Lesen Sie die Daten aus dieser Datei ein und rechnen Sie per Octave-Programm den Gesamtpreis für alle Tiere aus. Die Anzahl der Zeilen und der genaue Dateinhalt sei Ihnen vorab nicht bekannt. Bekannt ist nur das Datenformat wie folgt:
Nr. Name Einzelpreis Stueck 1 Affe 15000.50 2 2 Loewe 11000.90 1 3 Nashorn 45000.10 1 4 Elefant 51245.90 3 5 Tiger 9000.70 2 6 Maus 34.90 12
Eine einfache Lösung ohne Schnickschnack (Fehlerüberprüfungen etc.) für dieses Beispiel könnte wie folgt aussehen:
clear; close all; clc; datei = fopen ("c:/tmp/daten1.txt", "r"); gesamtpreis = 0; % Kopfzeile einlesen [nr, name, preis, stk] = fscanf(datei, "%s %s %s %s", "C"); while(feof(datei) == 0) % Datensätze einlesen [nr, name, preis, stk] = fscanf(datei, "%d %s %f %d", "C"); gesamtpreis += preis*stk; end fclose(datei); disp("Gesamtpreis = "); format long; disp(gesamtpreis);
Ausgabe:
Gesamtpreis = 258159.900000000
Datencontainer
[Bearbeiten]Datenstrukturen
[Bearbeiten]Pseudocode:
STRUKTUR s ZAHL a VEKTOR b STRING c END
Octave-Code:
s.a = 45.9; s.b = [1 2 3 4 5]; s.c = "Hallo!"; s
Ausgabe:
s = scalar structure containing the fields: a = 45.90000000000000 b = 1 2 3 4 5 c = Hallo!
Um ein paar weitere Möglichkeiten zum Handling mit Datenstrukturen aufzuzeigen, sei folgender Code aufgeführt.
Datei addsub.m
function res = addsub(a, b) res.x = a + b; res.y = a - b; end
Datei test1.m
clear; clc; addsub(10, 50) r = addsub(30, 70) r.x r.y ++r.x
Ausgabe:
ans = scalar structure containing the fields: x = 60 y = -40 r = scalar structure containing the fields: x = 100 y = -40 ans = 100 ans = -40 ans = 101
Die Funktion "addsub" liefert die Struktur res mit zwei Zahlenwerten. Die Elemente der Datenstruktur können auch außerhalb der Funktion angesprochen werden. Auch gerechnet werden kann mit diesen Elementen.
Cell Arrays
[Bearbeiten]Manchmal kann es sinnvoll sein mehrere Variablen verschiedenen Typs und Größe in einer Variablen zu speichern. Dies funktioniert ähnlich wie bei Vektoren. Es werden aber geschweifte Klammern verwendet.
Eingabe:
c = {"Hallo Welt!", [2 2], 44} c{1} c{1:2}
Ausgabe:
c = { [1,1] = Hallo Welt! [1,2] = 2 2 [1,3] = 44 } ans = Hallo Welt! ans = Hallo Welt! ans = 2 2
Elemente des Cell Arrays können auch wieder mit Variablen anderen Typs überschrieben werden.
c = {"Hallo Welt!", [2 2], 44}; c{1} = 5; c
Ausgabe:
c = { [1,1] = 5 [1,2] = 2 2 [1,3] = 44 }
Objektorientierte Programmierung
[Bearbeiten]Octave unterstützt auch objektorientierte Programmierung. Dieses Thema ist aber etwas für fortgeschrittene Anwender und wird hier nicht behandelt. Wen es trotzdem interessiert, der sei auf die Octave-Dokumentation verwiesen.
Octave GUI
[Bearbeiten]Das GUI-Programm von Octave entspricht im Wesentlichen anderen Programmier-Benutzeroberflächen, wie z.B. Eclipse oder Code::Blocks. Nachfolgend ist ein Screenshot des Octave-GUI mit einigen Anmerkungen dargestellt.
Probieren Sie einfach die Möglichkeiten der zur Verfügung gestellten GUI aus.
Komplexere Aufgaben
[Bearbeiten]- Berechnen Sie die Fläche, den Umfang, die Seitenlängen, den Inkreis und den Umkreis eines Dreiecks. Stellen Sie das Dreieck inklusive In- und Umkreis grafisch dar. Speichern Sie die Daten in einer Datei. Die drei Eckpunkte dieses Dreiecks sollen vom Benutzer beliebig vorgegeben werden.
- Die Werte einer beliebig großen quadratischen Matrix seien in einer Datei gespeichert. Lesen Sie diese Datei ein und berechnen Sie daraus die Determinante der Matrix, die inverse Matrix, die Eigenvektoren und -werte, die Spur. Führen Sie die LR-Zerlegung durch. Geben Sie diese Werte am Bildschirm aus.
Ausblick
[Bearbeiten]Dies war eine kurze Einführung in die Berechnungs- und Darstellungsmöglichkeiten mit Octave. Es sollten etliche relevante Themen behandelt, oder zumindest kurz angesprochen worden sein. Wem dieser Text nicht ausreichend ist, der sei auf die entsprechende weiterführende Literatur, die Octave-Hilfefunktion und die Octave-Dokumentation verwiesen. Octave kennt noch viel mehr Befehle, als hier dargestellt wurden. Aber auch Octave selbst ist erweiterbar. Man siehe z.B. Octave Packages (https://gnu-octave.github.io/packages/) oder man schreibt selbst Erweiterungen.