Hubert Selhofer, mit Änderungen von Marcel Oliver
Date: 2001/11/09
![\includegraphics[height=10cm,angle=270]{sombr.ps}](img1.gif)
Octave ist eine interaktive Scriptsprache, die speziell für vektorisierbare Berechnungen optimiert ist und dabei Standardroutinen der numerischen Mathematik (z.B. EISPACK oder LAPACK) auf einfache Weise zugänglich macht.
Der Syntax von Octave ist dem proprietären Matlab sehr ähnlich, d.h. ein Octave Programm kann meist auch von Matlab ausgeführt werden. Die Rückwärtskompatibilität ist nicht immer gegeben, da Matlab besonders im Grafikbereich um einen erheblich größeren Funktionsumfang verfügt.
octave:1> help eig
| < | kleiner | <= | kleiner oder gleich | & | und |
| > | größer | >= | größer oder gleich | | | oder |
| == | gleich | <> | ungleich | ~ |
nicht |
octave:1> x12 = 1/8, long_name = 'Ein String' x12 = 0.12500 long_name = Ein String octave:2> sqrt(-1)-i ans = 0 octave:3> x = sqrt(2); sin(x)/x ans = 0.69846Und hier ein Script doless, der in der Datei doless.m gespeichert ist:
eins = 1; zwei = 2; drei = eins + zwei;Aufruf des Scripts:
octave:1> doless octave:2> whos *** local user variables: prot type rows cols name ==== ==== ==== ==== ==== wd real scalar 1 1 drei wd real scalar 1 1 eins wd real scalar 1 1 zwei
Matrizen und Vektoren sind die wichtigsten Grundbausteine zur Programmierung in Octave.
v = [ 1 2 3 ]
v = [ 1; 2; 3 ]
Anfang[:Inkrement]:Ende
octave:1> x = 3:6
x =
3 4 5 6
octave:2> y = 0:.15:.7
y =
0.00000 0.15000 0.30000 0.45000 0.60000
octave:3> z = pi:-pi/4:0
z =
3.14159 2.35619 1.57080 0.78540 0.00000
Eine Matrix
wird erzeugt durch:
octave:1> A = [ 1 2; 3 4]
A =
1 2
3 4
Matrizen können folgenderweise aus Teilmatrizen zusammengesetzt
werden:
octave:2> b = [5; 6];
octave:3> M = [A b]
M =
1 2 5
3 4 6
Für einige wichtige
-Matrizen existieren eigene Befehle.
Falls m gleich n ist, muß nur ein Argument angegeben werden.
octave:1> A = [1 2; 3 4]; B = 2*ones(2,2);
octave:2> A+B, A-B, A*B
ans =
3 4
5 6
ans =
-1 0
1 2
ans =
6 6
14 14
Während z.B. * die standard Matrixmultiplikation bezeichnet, gibt es alle Operatoren mit vorangestelltem Punkt für elementweise Verknüpfung: .*, ./, .^, u.s.w.
octave:1> A = [1 2; 3 4]; A.^2 % elementweise Potenz
ans =
1 4
9 16
octave:2> A^2 % Zum Vergleich die matrixweise Potenz
ans =
7 10
15 22
octave:1> A = [1 2 3; 4 5 6]; v = [7; 8];
octave:2> A(2,3) = v(2)
A =
1 2 3
4 5 8
octave:3> A(:,2) = v
A =
1 7 3
4 8 8
octave:4> A(1,1:2) = v'
A =
7 8 3
4 8 8
A\b löst die Gleichung Ax = b.
Falls A eine
-Matrix ist, wird Gaußelimination
verwendet, sonst wird via QR-Zerlegung eine Lösung im Sinne der
kleinsten Fehlerquadrate berechnet. Ist A schlecht konditioniert
oder singulär, wird eine Warnung ausgegeben.
Traditionell sind Funktionen ebenfalls Textdateien mit Suffix .m. Im Unterschied zu Skripts können Funktionen mit Argumenten aufgerufen werden, und alle innerhalb der Funktion verwendeten Variablen sind lokal (sie beeinflussen die vorher definierten Variablen nicht).
Eine Funktion f, die in der Datei f.m gespeichert ist.
function y = f (x)
y = cos(x/2)+x;
end
In Octave kann man--sinnvollerweise--beliebig viele Funktionen in einer Skriptdatei definieren. Matlab hingegen lässt strikt nur eine Funktion pro .m Datei zu, und der Funktionsname muss mit dem Dateinamen übereinstimmen. Falls Kompatibilität mit Matlab wichtig ist, sollte diese Einschränkung auch auf Octave-Programme angewandt werden.
Eine Funktion dolittle, die in der Datei dolittle.m gespeichert ist.
function [out1,out2] = dolittle (x)
out1 = x^2;
out2 = out1*x;
end
Aufruf der Funktion:
octave:1> [x1,x2]=dolittle(2) x1 = 4 x2 = 8 octave:2> whos *** currently compiled functions: prot type rows cols name ==== ==== ==== ==== ==== wd user function - - dolittle *** local user variables: prot type rows cols name ==== ==== ==== ==== ==== wd real scalar 1 1 x1 wd real scalar 1 1 x2Offensichtlich waren die beiden Variablen out1, out2 in dolittle lokal. Eine vorher definierte Variable out1 oder out2 wird durch den Aufruf der Funktion nicht beeinflußt.
global name deklariert name als globale Variable.
Eine Funktion foo in der Datei foo.m:
function out = foo(arg1,arg2) global N % verwende N als globale Variable <Berechnung> endWird N in der Funktion verändert, ändert das auch den ursprünglichen Wert von N im ,,workplace``.
Die Syntax von for- und while-Schleifen wird an folgenden Beipielen klar:
for n = 1:10
[x(n),y(n)]=dolittle(n);
end
while t<T
t = t+h;
end
For-Schleife rückwärts:
for n = 10:-1:1 ...
Bedingte Verzweigungen lassen sich so programmieren:
if x==0
error('x ist 0!');
else
y = 1/x;
end
switch pnorm
case 1;
sum(abs(v))
case inf;
max(abs(v))
otherwise
sqrt(v'*v)
end
Berechne mit der Mittelpunktsregel:
function y = gauss(x)
y = exp(-x.^2/2);
end
function S = mpr(fun,a,b,N)
h = (b-a)/N;
S = h*sum(feval(fun,[a+h/2:h:b]));
end
Jetzt kann man die Funktion gauss durch folgenden Aufruf
integrieren:
octave:1> mpr('gauss',0,5,500)
Schleifen und Funktionsaufrufe, insbesondere über den Umweg feval, sind sehr teuer. Deswegen möglichst alle Operationen vektorisieren.
Wir programmieren die Mittelpunktsregel aus dem vorherigen Abschnitt
mit einer for-Schleife (Datei mpr_langsam.m):
function S = mpr_langsam(fun,a,b,N)
h = (b-a)/N; S = 0;
for k = 0:(N-1),
S = S + feval(fun,a+h*(k+1/2));
end
S = h*S;
end
Man vergleiche die Ausführungszeiten:
octave:1> t = cputime;
> Int1=mpr('gauss',0,5,500); t1=cputime-t;
octave:2> t = cputime;
> Int2=mpr_langsam('gauss',0,5,500); t2=cputime-t;
octave:3> Int1-Int2, t2/t1
ans = 0
ans = 45.250
octave:1> for k = .1:.2:.5,
> fprintf('1/%g = %10.2e\n',k,1/k); end
1/0.1 = 1.00e+01
1/0.3 = 3.33e+00
1/0.5 = 2.00e+00
Soll eine Funktion y=f(x) geplottet werden, geht man praktischerweise folgendermassen vor:
x = x_min:schrittweite:x_max;(Siehe auch Abschnitt 2.1.)
y = f(x);Wichtig: Damit f elementweise operiert, müssen die Operatoren .+, .-, .^ usw. anstelle der üblichen +, - und ^ verwendent werden! (Siehe Abschnitt 2.4.)
plot(x,y); grid; replot
octave:1> x = -10:.1:10; octave:2> y = sin(x).*exp(-abs(x)); octave:3> plot(x,y); grid; replot
![\includegraphics[height=7cm,angle=270]{2d-plot1.ps}](img11.gif)
octave:1> x = -2:0.1:2; octave:2> [xx,yy] = meshgrid(x,x); octave:3> z = sin(xx.^2-yy.^2); octave:4> mesh(x,x,z);
![\includegraphics[height=8cm,angle=270]{3d-plot1.ps}](img12.gif)
Erzeugen Sie eine Matrix A und einen Vektor b mit
A = reshape(1:4,2,2).'; b = [36; 88]; A\b [L,U,P] = lu(A) [Q,R] = qr(A) [V,D] = eig(A) A2 = A.'*A; R = chol(A2) cond(A)^2 - cond(A2)
Berechnen Sie ein Matrix-Vektor-Produkt einer
-Zufallsmatrix mit einem Zufallsvektor, indem Sie einerseits die
eingebaute Funktion *, andererseits for-Schleifen
verwenden. Vergleichen Sie die Rechenzeiten beider Lösungen.
A = rand(100); b = rand(100,1);
t = cputime;
v = A*b; t1 = cputime-t;
w = zeros(100,1);
t = cputime;
for n = 1:100,
for m = 1:100
w(n) = w(n)+A(n,m)*b(m);
end
end
t2 = cputime-t;
norm(v-w), t2/t1
ans = 0
ans = 577.00
Berechnen Sie alle Nullstellen des Polynoms
Zeichnen Sie diese Nullstellen in der komplexen Ebene als Punkte ein, und fügen Sie einen Einheitskreis hinzu (Hinweis: hold, real, imag).
bdf6 = [147/60 -6 15/2 -20/3 15/4 -6/5 1/6];
R = eig(compan(bdf6));
plot(R,'+'); hold on
plot(exp(pi*i*[0:.01:2]));
if any(find(abs(R)>1))
fprintf('BDF6 ist instabil\n');
else
fprintf('BDF6 ist stabil\n');
end
![\includegraphics[height=8cm,angle=270]{bdf6.ps}](img17.gif)
Zeichnen Sie den Graphen der Funktion
x = -3:0.1:3;
[xx,yy] = meshgrid(x,x);
z = exp(-xx.^2-yy.^2);
mesh(x,x,z);
title('exp(-x^2-y^2)');
replot;
err = zeros(15,1); co = zeros(15,1);
for k = 1:15
H = hilb(k);
b = ones(k,1);
err(k) = norm(H\b-invhilb(k)*b);
co(k) = cond(H);
end
semilogy(1:15,err,'r',1:15,co,'x');
Berechnen Sie zu beliebig vorgegebenen Punkten (xj,yj), die durch zwei Vektoren x und y gegeben sind, die Ausgleichsgerade (im Sinne der kleinsten Fehlerquadrate). Zeichnen Sie die Punkte und die Gerade.
function coeff = ausgl(x,y)
n = length(x);
A = [x ones(n,1)];
coeff = A\y;
plot(x,y,'x');
hold on
interv = [min(x) max(x)];
plot(interv,coeff(1)*interv+coeff(2));
end
Schreiben Sie ein Programm, das beliebige Funktionen f in einer
Variablen auf einem Intervall [a,b] numerisch integriert. Verwenden
sie die Trapezregel (
h = (b-a)/N):
function S = trapez(fun,a,b,N)
h = (b-a)/N;
% fy = feval(fun,[a:h:b]); besser:
fy = feval(fun,linspace(a,b,N+1));
fy(1) = fy(1)/2;
fy(N+1) = fy(N+1)/2;
S = h*sum(fy);
end
function y = f(x)
y = exp(x);
end
for k=1:15;
err(k) = abs(exp(1)-1-trapez('f',0,1,2^k));
end
loglog(1./2.^[1:15],err);
hold on;
loglog(1./2.^[1:15],err,'x');
title('Trapezregel, f(x) = exp(x)');
xlabel('Schrittweite');
ylabel('Fehler');
replot;
This document was generated using the LaTeX2HTML translator Version 98.1p1 release (March 2nd, 1998)
Copyright © 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
The command line arguments were:
latex2html -split 0 -no_navigation -show_section_numbers octave.tex.
The translation was initiated by Marcel Oliver on 2001-12-02