12 Schleifen

12 Schleifen

In MATLAB und beim Programmieren im Allgemeinen sind Schleifen (loops) ein mächtiges Werkzeug, das einem das Leben oft erleichtert und es einem ermöglicht Dinge auszurechnen, von denen man sonst nicht einmal träumen könnte. Umso wichtiger ist es, zu wissen, wie man sie korrekt verwendet.

Generell benutzt man Schleifen, wenn man eine Berechnung hat, die sich mehrmals genau gleich wiederholt und bei der die Berechnung im neuen Schritt auf das Ergebnis aus dem vorherigen Schritt zurückgreifen muss.

Ein GIF ist auch eine Schleife, das reicht mir als Grund.

2 Loop-Typen - 2 Anwendungsgebiete

Grundsätzlich gibt es zwei unterschiedliche Arten von Schleifen:
for- und while- Schleifen.
Jede hat ihr eigenes Anwendungsgebiet, und obwohl man eine while-Schleife in einem for-Szenario und eine for-Schleife in einem while-Szenario verwenden kann sollte man dies trotzdem vermeiden, denn sonst wird's unnötig kompliziert und genau dann passieren Fehler.

Ein klassisches Beispiel für eine Berechnung, die mittels Schleifen erledigt wird ist die Zahlen der Fibonacci-Folge zu berechnen.
Zur Erinnerung: die n-te Fibonacci Zahl ist die Summe aus den zwei vorhergehenden Zahlen:
0 1 1 2 3 5 8 13 21 34 55 89...

for

  • Anzahl an benötigten Schritten ist bekannt

    Die Anzahl an Schritten, die eine for-Schleife durchläuft ist gleich der Anzahl von Elementen, die "i" hat. i nimmt dabei in jedem Schritt den Wert an, der dem aktuellen Schritt entspricht.
    Also:
    i = 1:5, im dritten Schritt ist i=3
    i = [0 3 7 10 2], im dritten Schritt ist i=7
    aber beide Varianten ergeben fünf Schleifen-Durchläufe.
    Die Variable i kann somit innerhalb des Loops verwendet werden, um auf eine bestimmte Stelle in einem Array zuzugreifen, abhängig vom Schritt.

Es sollen die ersten 20 Zahlen der Fibonacci-Folge berechnet werden. Die Anzahl an benötigten Schritten ist also bekannt, wir verwenden deswegen eine for-Schleife.

while

  • Anzahl an benötigten Schritten unbekannt
    => Berechnung soll so lange wiederholt werden, bis eine bestimmte Bedinung erfüllt ist, von der man im Vorhinein nicht weiß, nach wie vielen Schritten das der Fall ist.

    Eine while-Schleife wird solange wiederholt, solange das Argument neben "while" ein logisches true / 1 ergibt.
    Möchte man abhängig von der Anzahl an vorhergegangenen Iterationen / Schritten auf eine Bestimmte Stelle in einem Array zugreifen benötigt man eine zusätzliche Variable, zu der am Ende jedes Schritts 1 dazugezählt wird. (z.B. i = i +1;)

Die letzte Zahl in unserer Fibonacci-Folge soll kleinergleich 4000 sein. Da wir die Fibonacci-Folge aber noch nicht kennen, wissen wir nicht, wieviele Zahlen das sein werden. Wir verwenden also eine while-Schleife, die so lange ausgeführt wird, solange die Summe der letzten beiden Elemente unserer Folge kleinergleich dem Maximum ist.

ACHTUNG: while dumm == true...

Die Verwendung von while-Schleifen birgt einige Risiken, die sich grausam an einem rächen können, wenn man nicht aufpasst:

  • nachdem man nicht weiß, wann die Bedingung für die Schleife nicht mehr wahr ist kann es passieren, dass die Schleife eine gefühlte Ewigkeit läuft. Es macht deswegen oft Sinn, eine zweite Bedingung einzubauen, die besagt, dass nach soundsovielen Iterationen abgebrochen wird.
    Zum Beispiel: while Wert <= bedingung && iteration <= maxiterationen
  • Die Bedingung ist von Anfang an nicht true: Dann wird die Schleife nie ausgeführt und im schlimmsten Fall bemerkt man das nicht einmal, da es ja keine Fehlermeldung deswegen gibt.
  • Die Bedingung bleibt für immer true: Dann läuft die Schleife auch für immer und das Universum endet vermutlich noch vor der Berechnung.

Außerdem sollte man eine while-Schleife nicht benutzen, wenn man schon weiß, wieviele Schritte man machen wird. Dadurch wird nämlich alles unnötig kompliziert und jede zusätzliche Zeile Code erhöht das Fehlerpotential!

Beispiel für eine while-Schleife, die eigentlich eine for-Schleife sein will.

Laufzeit optimieren

Wenn man ein paar simple Dinge beachtet kann man sich viel unnötige Wartezeit beim Ausführen eines Programms ersparen. Davon sind insbesondere Loops betroffen, da sich die Zeitersparniss da ja um die Anzahl der Schritte vervielfacht.

Oben sind einige Beispiele für die immer gleiche Berechnung gegeben.

  1. In jedem Schritt wird das Ergebnis im Command-Window von MATLAB dargestellt, da das Semikolon am Ende fehlt. Das wird gerade bei größeren Arrays sehr schnell sehr zeitaufwendig und sollte unbedingt vermieden werden!
  2. Kein Output ins Command-Window mehr, aber ein anderes Problem besteht weiterhin: In jedem Schritt wird die Variable y um einen Wert länger. Dadurch geht viel Zeit verloren, in der MATLAB mehr Speicherplatz für die Variable allokieren muss.
  3. Da wir ja wissen, wie groß y sein wird initialisieren wir die Variable mit Nullen als Platzhalter. Dadurch muss nicht in jedem Schritt der Speicherplatz verändert werden. Wieder enorm viel Zeit gespart!
  4. Zum Schluss fällt uns ein das bei dieser Berechnung das Ergebnis vom neuesten Schritt nicht vom vorherigen Ergebnis abhängt. Wir brauchen also gar keine Schleife! Die Lösung: Vektorisierung. Einfach alles mit einem Vektor berechnen. Das geht nochmal um Welten schneller als eine noch so durch-optimierte Schleife.

Riesige Zeitersparnis, wenn das Ergebnis nicht im Command Window angezeigt wird.

Es geht immer besser: Array initialisieren, und wenn möglich vektorisieren.

Wenn nur sehr wenige Schritte durchgeführt werden kann das Initialisieren sogar mehr Zeit kosten. Aber bei wenigen Schritten sind das eh nur Mikrosekunden.