Ing Mathematik: Numerische Mathematiksysteme am Beispiel von Octave
Hallo Welt und allgemeine HinweiseBearbeiten
Was ist OctaveBearbeiten
- 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 installierenBearbeiten
MS WindowsBearbeiten
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.
LinuxBearbeiten
Entweder ist Octave bereits standardmäßig installiert, ansonsten ist die Installation mittels Paketmanagementsystem einfach möglich.
Octave startenBearbeiten
MS WindowsBearbeiten
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.
LinuxBearbeiten
In einer Linux-Konsole den Befehl "octave" eintippen und das Programm startet.
Ein paar Worte zur ErklärungBearbeiten
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 Juli 2021 die Version 6.3, 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 Version 5.2 aktualisiert. Dieser Mischmasch sollte aber kein Problem darstellen.
Getestet wurden die Beispiele unter dem Betriebssystem MS Windows 10.
Ein erstes ProgrammBearbeiten
Kommentare werden in Octave mit dem Prozentzeichen (%) oder alternativ mit der Raute (#) eingeleitet. Sie werden vom Octave-Interpreter ignoriert. 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 TaschenrechnerBearbeiten
AllgemeinesBearbeiten
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.66791
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 % Die Kreisfläche 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 Flächenwert ausgegeben werden, nicht der Radius.
Eingabe:
% Der Kreisradius sei 10 10; % Die Kreisfläche 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 long E pi % usw.
Ausgabe:
ans = 3.1416 ans = 3.14159265358979 ans = 3.14159265358979E+000
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 OctaveBearbeiten
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 -- 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:
Next: Preface, Up: (dir) GNU Octave (version 5.2.0) ************************** This manual documents how to run, install and port GNU Octave, as well as its new features and incompatibilities, and how to report bugs. It corresponds to GNU Octave version 5.2.0. * Menu: * Preface:: * Introduction:: A brief introduction to Octave. * Getting Started:: * Data Types:: * Numeric Data Types:: * Strings:: * Data Containers:: * Variables:: * Expressions:: * Evaluation::
etc.
AufgabenBearbeiten
- 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 ScriptspracheBearbeiten
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.
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!
BlockkommentareBearbeiten
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 #}
VariablenBearbeiten
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
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
ZahlenkolonnenBearbeiten
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
VerzweigungenBearbeiten
Die IF-VerzweigungBearbeiten
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-VerzweigungBearbeiten
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
SchleifenBearbeiten
Die WHILE-SchleifeBearbeiten
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-SchleifeBearbeiten
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-SchleifeBearbeiten
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
Schleifen abbrechenBearbeiten
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
AufgabenBearbeiten
- Berechnen Sie die Summe der ersten 100 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).
Grafiken zeichnenBearbeiten
2DBearbeiten
Graph einer FunktionBearbeiten
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^A, A must be square error: evaluating binary operator `^' near line 2, column 16 error: evaluating binary operator `+' near line 2, column 13 error: evaluating assignment expression near line 2, column 3 error: near line 2 of file `c:/tmp\test1.m'
Ausgabe:
Graphen mehrerer Funktionen und weiteresBearbeiten
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 ParameterdarstellungBearbeiten
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ärkeBearbeiten
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 ausgebenBearbeiten
x = -10:0.1:10; plot (x, sin (x), "LineWidth", 2); text (2.7, 0.8, "Das ist die sin-Funktion");
Ausgabe:
Logarithmische AchseneinteilungBearbeiten
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.
AufgabenBearbeiten
- 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.
3DBearbeiten
Räumliche KurvenBearbeiten
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ächenBearbeiten
ezsurfBearbeiten
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 Octave-Hilfe).
surf und meshBearbeiten
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 KegelBearbeiten
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;
AufgabenBearbeiten
- 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:
WeiteresBearbeiten
subplotBearbeiten
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.
figureBearbeiten
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 zeichnenBearbeiten
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);
AufgabenBearbeiten
- 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 MatrizenBearbeiten
VektorenBearbeiten
Vektoren sollten jedem aus der Linearen Algebra bekannt sein.
Zeilen- und SpaltenvektorenBearbeiten
% 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 VektorelementeBearbeiten
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 VektorenBearbeiten
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 SkalarenBearbeiten
faktor = 3 v = [1, 2, 3]; res = faktor * v
Ausgabe:
res = 3 6 9
SkalarproduktBearbeiten
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
VektorproduktBearbeiten
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 VektorBearbeiten
v1 = [1, 2, 3]; v2 = [5; 6; 7]; res1 = v1' res2 = v2'
Ausgabe:
res1 = 1 2 3 res2 = 5 6 7
Einige weitere VektorfunktionenBearbeiten
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
MatrizenBearbeiten
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 MatrizenelementeBearbeiten
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 MatrizenBearbeiten
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 MatrixBearbeiten
m = [1, 2, 3; 4, 5, 6]; m'
Ausgabe:
ans = 1 4 2 5 3 6
Rang einer MatrixBearbeiten
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 MatrixBearbeiten
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: inverse: matrix singular to machine precision, rcond = 0 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 MatrixBearbeiten
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.
TeilmatrizenBearbeiten
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
EinheitsmatrizenBearbeiten
eye(3,2)
Ausgabe:
ans = 1 0 0 1 0 0
NullmatrizenBearbeiten
zeros(2,3)
Ausgabe:
ans = 0 0 0 0 0 0
DiagonalmatrizenBearbeiten
diag([1, 2, 3])
Ausgabe:
ans = 1 0 0 0 2 0 0 0 3
Spur einer MatrixBearbeiten
trace([1,2,3; 6,9, 0])
Ausgabe:
ans = 10
LR-Zerlegung einer MatrixBearbeiten
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
EigenwerteBearbeiten
a = [5 8 1 3]; % Eigenvektoren und Eigenwerte [ev, ew] = eig(a)
Ausgabe:
ev = 0.97014 -0.89443 0.24254 0.44721 ew = 7 0 0 1
Die Eigenwerte sind hier und . Die Eigenvektoren sind [0.97014 0.24254] bzw. [-0.89443 0.44721]. Da das Gleichungssystem singulär ist, sind alle Lösungsvektoren Vielfache dieser Eigenvektoren.
Schwach besetzte MatrizenBearbeiten
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 ZufallswertenBearbeiten
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.
AufgabenBearbeiten
- 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 ZahlenBearbeiten
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 rechnenBearbeiten
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 ZahlenebeneBearbeiten
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;
AufgabenBearbeiten
- 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.
FunktionenBearbeiten
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 schreibenBearbeiten
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-FunktionenBearbeiten
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
FunktionsstringBearbeiten
addiere = "a + b"; a = 5; b = 10; z = eval(addiere)
Ausgabe:
z = 15
Anonyme FunktionenBearbeiten
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 bestimmenBearbeiten
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 VariablenBearbeiten
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
AufgabenBearbeiten
- 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.
PolynomeBearbeiten
Einzelne Polynomwerte berechnenBearbeiten
% 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 zeichnenBearbeiten
% 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 bestimmenBearbeiten
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).
AufgabenBearbeiten
- Berechnen Sie den Wert für x = 3 des Polynoms .
- Berechnen Sie die Nullstellen von .
- Zeichnen Sie das Polynom im Intervall .
Lineare GleichungssystemeBearbeiten
Sei ein lineares Gleichungssystem. sei die Koeffizientenmatrix, der Lösungsvektor und ein bekannter Vektor.
Einfache Berechnung mittels Gauß-VerfahrenBearbeiten
Beispiel:
A = [5 1 0 2]; b = [1 2]; x = A \ b
Ausgabe:
x = 0 1
Das gmres-VerfahrenBearbeiten
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)
AufgabeBearbeiten
- 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 GleichungssystemeBearbeiten
fsolveBearbeiten
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.
GleichungssystemeBearbeiten
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 0 info = 1 x = 2 -1 fval = 0 0 info = 1 x = 0 0 fval = 0 0 info = 1
AufgabenBearbeiten
- 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):
InterpolationBearbeiten
Eindimensionale InterpolationBearbeiten
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 InterpolationBearbeiten
Bezüglich mehrdimensionaler Interpolation siehe die Hilfefunktion zu "interp2", "interp3" und "interpn".
AufgabeBearbeiten
- 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");
DifferenzialrechnungBearbeiten
Polynome differenzierenBearbeiten
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 differenzierenBearbeiten
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".
AufgabenBearbeiten
- 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.
IntegralrechnungBearbeiten
Polynome integrierenBearbeiten
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ß-QuadraturBearbeiten
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-RegelBearbeiten
Berechnen Sie diesmal das Integral mittels Lobatto-Quadratur.
f = inline("x.^2"); v = quadl (f, 0, 3)
Ausgabe:
v = 9
Zwecks Übung sei nachfolgend nochmals dieses Beispiel berechnet. Diesmal wird aber eine anonyme Funktion verwendet.
v = quadl (@(x) x.^2, 0, 3)
AufgabenBearbeiten
- 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 DifferenzialgleichungenBearbeiten
ode23, ode45 und lsodeBearbeiten
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.
AufgabenBearbeiten
- 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-TransformationBearbeiten
Für die Funktion "fft" siehe das Octave-Hilfesystem.
MengenrechnungBearbeiten
VereinigungsmengeBearbeiten
v1 = [1 2 3 4]; v2 = [2 4 6]; union(v1, v2)
Ausgabe:
ans = 1 2 3 4 6
SchnittmengeBearbeiten
v1 = [1 2 3 4]; v2 = [2 4 6]; intersect(v1, v2)
Ausgabe:
ans = 2 4
StochastikBearbeiten
Deskriptive StatistikBearbeiten
LageparameterBearbeiten
Arithmetischer Mittelwert:
vec = [1 2 3 4 5 12 13]; mw = mean(vec)
Ausgabe:
mw = 5.7143
Geometrischer Mittelwert:
vec = [1 2 3 4 5 12 13]; mw = mean(vec, "g")
Ausgabe:
mw = 4.0769
Harmonischer Mittelwert:
vec = [1 2 3 4 5 12 13]; mw = mean(vec, "h")
Ausgabe:
mw = 2.8646
Der Median oder Zentralwert läßt sich folgendermaßen berechnen:
vec = [1 2 3 4 5 12 13]; median(vec)
Ausgabe:
mw = 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.
StreuungsparameterBearbeiten
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
Zweidimensionale HäufigkeitsverteilungenBearbeiten
Kovarianz:
v1 = [1 2 3 1 1 6 7]; v2 = [7 9 6 2 5 9 6]; c = cov(v1, v2)
Ausgabe:
c = 2.3333
Korrelation:
v1 = [1 2 3 1 1 6 7]; v2 = [7 9 6 2 5 9 6]; c = corr(v1, v2)
Ausgabe:
c = 0.38156
Grafiken erzeugenBearbeiten
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:
AufgabenBearbeiten
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.
WahrscheinlichkeitsrechnungBearbeiten
KombinatorikBearbeiten
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
VerteilungenBearbeiten
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
warning: 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:
ZufallszahlengeneratorenBearbeiten
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 erstellenBearbeiten
InputBearbeiten
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 DialogeBearbeiten
Fehlermeldung:
errordlg("Fehlermeldung");
Warnung:
warndlg("Warnung");
Hilfedialog:
helpdlg
Abfragedialog:
button = questdlg ("Frage")
Eingabedialog:
in = inputdlg("Eingabe")
Messagebox:
h = msgbox ("Eine Mitteilung!");
Komplexere vorgefertigte DialogboxenBearbeiten
MenüboxBearbeiten
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
DialoglisteBearbeiten
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
FortschrittsbalkenBearbeiten
h = waitbar ([0.5])
Datei- und VerzeichnisdialogeBearbeiten
Dateidialog:
[fname, fpath, fltidx] = uigetfile ()
Ähnlich sind die Befehle "uiputfile" und "uigetdir". Dazu sei auf die Octave-Hilfe verwiesen.
Eigene Dialoge kreierenBearbeiten
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/catchBearbeiten
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 AusgabeBearbeiten
Formatierte Ausgabe am Bildschirm, formatiertes Lesen von der TastaturBearbeiten
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 schreibenBearbeiten
Bezüglich der Funktionen
- sprintf
und
- sscanf
sei auf die Octave-Hilfefunktion verwiesen.
Lesen und Schreiben von einer DateiBearbeiten
Datei schreibenBearbeiten
% 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 lesenBearbeiten
% 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üfenBearbeiten
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 errorBearbeiten
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 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: evaluating if command near line 4, column 1 error: near line 6 of file `c:/tmp\test1.m'
AufgabenBearbeiten
- 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
DatencontainerBearbeiten
DatenstrukturenBearbeiten
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 = { a = 45.900 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 = { x = 60 y = -40 } r = { 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 ArraysBearbeiten
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 = (, [1] = Hallo Welt! [2] = 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 ProgrammierungBearbeiten
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 GUIBearbeiten
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 AufgabenBearbeiten
- 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.
AusblickBearbeiten
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-Forge (https://octave.sourceforge.io/packages.php) oder man schreibt selbst Erweiterungen.