Subsections


6.3 Wiederholung

Ein wichtiges Konstruktionsmittel in Programmiersprachen ist die Wiederholung. Sie erlaubt die wiederholte Ausführung einer Anweisungsfolge, ohne dass man gezwungen ist, die entsprechenden Anweisungen mehrmals zu schreiben. Die Anzahl der Wiederholungen wird dabei durch einen Schleifenkopf bestimmt.

In MATLAB gibt es zwei Schleifentypen, die Zählschleife for und die bedingte Schleife while. Beide Schleifentypen können darüberhinaus mit dem Befehl break abgebrochen werden.

Schleifenkonstrukte haben eine große Bedeutung bei allen Iterationen, wo aus bekannten Werten neue erzeugt werden. Als Beispiel soll folgende Rekursionsformel dienen:

$\displaystyle a_1=0 \; , \; a_2=1 \; , \; a_k = \frac{a_{k-2} + a_{k-1}}{2} \qquad \forall k \geq 3 \; .$ (6.1)

In vielen anderen Fällen, hat sich durch Matrix- und Arrayoperatoren, durch die Doppelpunktnotation und durch eine Fülle von MATLAB-Befehlen die Notwendigkeit für Schleifenkonstrukte verringert. Als wichtige Regel gilt, dass allen Befehlen, die direkt auf Felder angewandt werden, gegenüber einer expliziten Programmierung mit Schleifen Vorrang zu geben ist. Bei allen internen Befehlen kann die zeitliche Optimierung durch MATLAB viel besser durchgeführt werden. Außerdem werden bei Vermeidung von Schleifen die Programme weit einfacher, kürzer und übersichtlicher. Daher sollte man sich immer die Frage stellen, ob man eine Schleife wirklich braucht oder ob man die Aufgabe nicht besser anders erledigen kann.


6.3.1 Zählschleife

In der Zählschleife wird explizit angegeben, wie oft ein Anweisungsblock ausgeführt werden soll.

 for Schleifenindex = Feld
    Anweisungsblock
 end

Der Schleifenindex nimmt dabei nacheinander alle Werte der Elemente eines beliebigen Feldes ``Feld'' an. Der Ablauf erfolgt dabei entsprechend den Regeln der linearen Feldindizierung, zuerst entlang der ersten Dimension, dann der zweiten, usw.. Für jeden Wert des Schleifenindex wird der Anweisungsblock einmal ausgeführt und danach die Schleife beendet.

Durch eine Kombination mit einer IF-Entscheidung kann unter Verwendung des Befehls break die Schleife jederzeit beendet werden.

 for Schleifenindex = Feld
    Anweisungsblock 1
    if Bedingung, break; end
    Anweisungsblock 2
 end

Natürlich können auch Schleifen ineinander geschachtelt werden, wobei zu jedem for ein end gehören muss. Bei geschachtelten Schleifen beendet der Befehl break die jeweils innere Schleife.

Der Schleifenindex hat am Ende der Abarbeitung den jeweils letzten Wert. Man kann daher überprüfen, ob es zur Ausführung des break-Befehls gekommen ist.


6.3.2 Die bedingte Schleife

Bei der bedingten Schleife (while) hängt die Anzahl der Durchläufe von einer logischen Bedingung im Schleifenkopf ab. Die Bedingung wird bei jedem Schleifendurchlauf am Beginn ausgewertet. Der Anweisungsblock wird nur dann ausgeführt, wenn die Bedingung erfüllt ist. Ist die Bedingung nicht erfüllt, wird die Schleife beendet.

 while Bedingung
    Anweisungsblock
 end

Ist die Bedingung schon am Anfang nicht erfüllt, wird der Anweisungsblock nie ausgeführt. Natürlich kann auch eine solche Schleife an jeder beliebigen Stelle durch eine break-Anweisung unterbrochen werden.

 while Bedingung
    Anweisungsblock 1
    if Abbruchbedingung, break; end
    Anweisungsblock 2
 end

In manchen Programmiersprachen gibt es eine sogenannte nichtabweisende Schleife (UNTIL-Schleife), die zumindest einmal durchlaufen wird. Eine solche gibt es in MATLAB nicht, man kann sie jedoch mit Hilfe einer ``Endlosschleife'' und eine break-Anweisung realisieren.

 while 1               % immer wahr
    Anweisungsblock
    if Bedingung, break; end
 end

Am Beispiel der ``Endlosschleife'' sollte auch klar werden, welche Gefahr in Schleifen steckt, wenn die Abbruchbedingungen nicht gut durchdacht sind. In solchen Fällen ist es möglich, dass Schleifen von selbst nicht mehr verlassen werden. Dies kann dann nur durch einen externen Abbruch des Programms erfolgen. Solche Fehler sollten daher vermieden werden.

MATLAB EXAMPLE:
Hier wird die Rekursionsformel

$\displaystyle a_1=0 \; , \; a_2=1 \; , \;
a_k = \frac{a_{k-2} + a_{k-1}}{2} \qquad \forall k \geq 3
$

für $ 1 \leq k \leq n$ ausgewertet und gezeigt, wie man bei einem Limit $ \vert a_{k}-a_{k-1}\vert<\epsilon$ die Berechnung abbricht.

n = 100; limit = 1.e-6;

a = zeros(1,n); a(2) = 1;
for k = 3:n
    a(k) = (a(k-1) + a(k-2)) / 2;
end

b = zeros(1,n); b(2) = 1;
for k = 3:n
    b(k) = (b(k-1) + b(k-2)) / 2;
    if abs(b(k)-b(k-1)) < limit 
        break; 
    end
end
b(k+1:end) = [];

c = zeros(1,n); c(2) = 1;
k = 2;
while abs(c(k)-c(k-1)) >= limit
    k = k + 1;
    if k > n, break; end
    c(k) = (c(k-1) + c(k-2)) / 2;
end
c(k:end) = [];
Die Realisierung erfolgt einmal mit einer for-Schleife ohne weitere Einschränkung, einmal mit einer for-Schleife mit zusätzlicher Verwendung des break-Befehls und einmal mit einer Kombination aus while-Schleife und break-Befehl.

Wann immer es möglich ist, empfiehlt es sich, Felder vor dem Gebrauch in ihrer maximalen Größe anzulegen, damit sie nicht innerhalb der Schleife immer dynamisch vergrößert werden müssen.

Mit dem Befehl c(k:end)=[] wird der nicht benötigte Rest des Feldes gelöscht.

Winfried Kernbichler 2005-04-26