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.
Wikipedia hat einen Artikel zum Thema:

.

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.

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.

 

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

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.

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

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

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.

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
Wikipedia hat einen Artikel zum Thema:


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
Wikipedia hat einen Artikel zum Thema:


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
Wikipedia hat einen Artikel zum Thema:


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.

Wikipedia hat einen Artikel zum Thema:


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)

Wikipedia hat einen Artikel zum Thema:


  • 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
Wikipedia hat einen Artikel zum Thema:


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".

  • 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
Wikipedia hat einen Artikel zum Thema:


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.

Wikipedia hat einen Artikel zum Thema:


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
Wikipedia hat einen Artikel zum Thema:


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

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
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.