Einführung in die MATLAB-Programmierung

5. Ablaufstrukturen

In einem Programm wird in weiten Teilen nichts anderes beschrieben als die Berechnung von Werten, die dann einem Namen zugeordnet werden. Dabei treten bestimmte Strukturen auf. Manchmal wiederholen sich dieselben oder ähnliche Anweisungen und sind wieder und wieder auszuführen. Manchmal sollen solche Anweisungen nur unter bestimmten Bedingungen durchgeführt werden. Wir bezeichnen diese Strukturen als Ablaufstrukturen. Die Anweisungen, die im Hinblick auf eine solche Struktur zusammengefaßt werden, etwa alle Anweisungen, die nur dann ausgeführt werden sollen, wenn eine bestimmte Bedingung erfüllt ist, bezeichnen wir als Anweisungsblock. Zusammen mit der Beschreibung der Ablaufstruktur bilden diese Anweisungsblöcke eine Verbundanweisung.
Solange man nur mit skalaren Größen arbeitet, unterscheiden sich die in Matlab verfügbaren Mittel zur Beschreibung der Ablaufstrukturen, kaum von denen anderer Programmiersprachen.

Verzweigungen können mit:

  1. if, elseif, else und end
  2. switch, case, otherwise und end
gebildet werden.

Schleifen können mit:

  1. for, break und end
  2. while, break und end
gebildet werden.

Die einzelnen Textbausteine einer Verbundanweisungen können jeweils einzeln in eigenen Zeilen eingegeben werden, Matlab erkennt von selbst, wann die Verbundanweisung beendet ist.
Die Bausteine können aber auch hintereinander in einer Zeile eingegeben werden, müssen dann aber durch Kommata oder Semikola voneinander getrennt werden. Ein Semikolon am Ende einer Anweisung hat dabei wie üblich die Bedeutung, die Ergebnisausgabe von Matlab zu unterdrücken, ein Komma hat diese Wirkung nicht.

5.1 Bedingte Anweisungsblöcke und Verzweigungen

Ein bedingter Anweisungsblock hat in Matlab die Form:
   if Bedingung
      bedingter Anweisungsblock
   end
Der Anweisungsblock wird nur dann ausgeführt, wenn die Bedingung wahr ist. Der Anweisungsblock kann beliebig viele Anweisungen, auch Verbundanweisungen enthalten. Verbundanweisungen können also geschachtelt werden.
Bedingungen können als beliebiger skalarer logischer Ausdruck angegeben werden. Falls der Ausdruck keinen skalaren Wert liefert, berechnet Matlab automatisch nach vorgegebenen Regeln einen skalaren Wert. Wir kommen darauf später noch zurück. Falls der Wert des Ausdruckes zwar skalar, aber verschieden von 0 (falsch) oder 1 (wahr) ist, ordnet Matlab ihm einen logischen Wert zu.
  • 0 (auch 0i) und [] sind falsch
  • NaN ist nicht zugelassen
  • alle anderen numerischen Werte, auch komplexe und Inf, sind wahr
Frage: Kann man statt if Wert==0 immer if Wert schreiben?

 if []
  'Wo nichts ist, kann auch nichts Wahres sein.'
  end
 if 1789
  'Stunde der Wahrheit.'
  end
ans =
Stunde der Wahrheit.
 if NaN
  'Weder Fisch noch Fleisch.'
  'Das ist nicht zugelassen.' 
  end
??? IF or WHILE condition is NaN
 if 3+5i
  'Die Wahrheit kann komplex sein.'
  end
ans =
  Die Wahrheit kann komplex sein.

Zwei alternativ auszuführende Anweisungsblöcke werden in Matlab mit Hilfe von else formuliert:

   if Bedingung
      bedingter Anweisungsblock
   else
      alternativer Anweisungsblock
   end
Wenn die Bedingung erfüllt ist, wird der bedingte Anweisungsblock ausgeführt, anderenfalls der alternative Anweisungsblock.

Man kann auch mehrere Bedingungen abprüfen lassen und jeder Bedingung einen Anweisungsblock zuordnen. Die Reihenfolge, in der die Bedingungen aufgelistet werden ist dabei von Bedeutung, sie bestimmt die Reihenfolge in der sie geprüft werden. Sobald eine wahre Bedingung gefunden wird, wird der zugehöhrige Anweisungsblock durchlaufen und die Verbundanweisung ist damit abgearbeitet. Man formuliert zusätzliche Bedingungen in Matlab mit Hilfe von elseif. elseif-Konstruktionen können mit einer else-Konstruktion abgeschlossen werden, müssen dies aber nicht.

    x=1848;
    if x >= 1e9
       [ num2str(1e-9*x) 'G' ]
     elseif x >= 1e6
       [ num2str(1e-6*x) 'M' ]  
     elseif x >= 1e3
       [ num2str(1e-3*x) 'k' ]
     else
       x
     end
   ans =
       1.848k
Frage: Wie läßt sich das obige Problem ohne else formulieren? Kann man die Abfragen vertauschen ohne das Ergebnis zu verändern?

5.2 Fallunterscheidungen.

Fallunterscheidungen stellen eine besondere Form der Verzweigung dar, bei der die Anweisungsblöcke einzelnen Werten eines einzigen Ausdruckes zugeordnet werden. Dieser Ausdruck kann einen skalaren numerischen Wert haben, er kann aber auch eine Zeichenkette als Wert haben.
Ähnlich wie bei der if-elseif-else-end Verzweigung gibt es auch bei der Fallunterscheidung die Möglichkeit, einen Block anzugeben, der dann auszuführen ist, wenn alle anderen Bedingungen zuvor nicht zugetroffen haben, er wird mit otherwise eingeleitet und muß wie der entsprechende else-Block der letzte Anweisungsblock in der Folge sein.
    Jahr=1438;
    switch Jahr
     case 1438
     'Melozzo da Forli'
     case 1450
     'Lucca Signorelli'
     case 1444
     'Sandro Botticelli'
     case 1436
     'Andrea del Verrocchio'
     end
   ans =
   Melozzo da Forli
    Person='Sandro Botticelli';
    switch Person
     case 'Sandro Botticelli'
      'geboren 1444'
     case 'Fra Angelico'
      'geboren 1387'
     otherwise
      [ Person 'ist unbekannt']
     end
   ans =
     geboren 1444
Mehrere Fälle kann man zu Zellen zusammenfassen, auf die wir erst später eingehen werden. Im Moment geben wir nur an, daß Zellen mit { } gebildet werden und daß die Elemente in der Zelle durch Kommata getrennt aufgelistet werden.
    switch Jahr
     case {1448,1449,1450,1451,1452}
       'Hieronymus Bosch'
     case 1470
       'Albrecht Dürer'
     otherwise
       'Wolf Huber'
     end
   ans =
        Wolf Huber
Wer mit der Programmiersprache C vertraut ist, sollte beachten, daß in Matlab bei einem switch-Verbund nur der erste Anweisungsblock ausgeführt, dessen Fallangabe zutrifft. Danach wird die Bearbeitung des switch-Verbundes beendet. Der switch-Verbund verhält sich hier also analog zum if-Verbund.

5.3 Zähl-Schleifen

for- oder Zähl-Schleifen sind solche, bei denen eine bestimmte Anweisungsfolge, der Schleifenblock eine vorgegebene Anzahl mal durchlaufen wird. Jedem Schleifendurchlauf wird mit Hilfe einer Schleifenvariablen ein bestimmter Wert, der Schleifenindex zugeordnet, der in der Schleife abgefragt werden kann. Wie oft die Schleife durchlaufen wird, steht schon vor Schleifenbeginn fest.
   
    sum=0;
    n=10;
    for ind=1:n; sum=sum+ind^2; end
    sum
   sum =
        385
for-Schleifen haben in Matlab die Form:
   for Schleifenvariable=Bereichsangabe
      ...
      Schleifenblock
      ...
      end
Man kann die gesamte Verbundanweisung in einer Zeile eingeben, muß dann aber die einzelnen Komponenten, insbesondere die Anweisungen des Schleifenblockes durch Kommata oder Semikola voneinander trennen. Die Semikola haben dabei die Bedeutung, die Ergebnisausgabe zu unterdrücken, die Kommata tun dies nicht.
Man kann die einzelnen Komponenten aber auch in jeweils eigenen Zeilen eingeben, ohne daß Fortsetzungspunkte erforderlich sind.
Matlab läßt vektorwertige Schleifenvariablen und recht allgemeine Angaben des Laufbereiches zu. Im Augenblick beschränken wir uns:
  • auf skalarwertige Laufvariablen,
  • auf Angaben des Laufbereiches in der Form Anfangswert:Schrittweite:Endwert wobei alle drei Angaben in Form skalarwertiger Ausdrücke gemacht werden können. Bei positiver Schrittweite ist der letzte angenommene Wert der Laufvariablen kleinergleich, bei negativer Schrittweite größergleich dem Endwert.
    Wird die Schrittweite nicht angegeben, erfolgt also die Angabe des Laufbereichs in der Form Anfangswert:Endwert, so wird implizit Schrittweite 1.0 verwendet.

    for ind=0:2/3:5/4
       ind
     end
     ind =
        0
      ind =
        0.6667
    for ind=-1/2:-1/3:-1
        ind
     end
     ind =
        -0.5000
     ind =
        -0.8333
Anfangs- und Endwert sowie Schrittweite werden bei der for-Schleife vor dem ersten Schleifendurchlauf bestimmt und können beim Schleifendurchlauf nicht mehr verändert werden. Im folgenden Beispiel ist der Anfangswert 1, der Endwert 10 und die Schrittweite 2, die Wertzuweisungen im Schleifenkörper wirken sich auf diese Werte nicht mehr aus. Die Klammerung der drei Ausgabevariablen bewirkt, daß diese hier in nur einer Zeile ausgegeben werden.
 clear all
 step=2;
 fine=10;
 for tt=step-1:step:fine
    tt=2*tt;
    step=2*step;
    fine=fine-1;
    [ tt step fine ]
    end
ans =
     2     4     9
ans =
     6     8     8
ans =
    10    16     7
ans =
    14    32     6
ans =
    18    64     5 
Die Ausdrücke, mit denen Anfangs-, Endwert und Schrittweite angegeben werden, müssen dementsprechend vor dem ersten Schleifendurchlauf schon definierte Werte aufweisen. Das ergibt sich schon daraus, daß bereits vor dem ersten Durchlauf festgestellt werden muß, ob ein solcher überhaupt stattfindet.
Bei der Angabe des Schleifenbereiches unterscheidet Matlab zwischen undefinierten Namen und solchen, mit undefinierten bzw. unbrauchbaren Werten. Ersteres führt zu einer Fehlermeldung, letzteres in der Regel dazu, daß die Schleife nicht durchlaufen wird. Von Bedeutung ist, daß ein Endwert Inf nicht zu unendlich vielen Durchläfen führt.
 m=[];
m =
     []
 for ii=0:m
    ii
  end
 clear all
 for ii=0:m
    ii
  end
??? Undefined function or variable 'm'.
 m=NaN;
 for ii=0:m
    ii
  end
 for ii=0:Inf
    ii
  end
ii =
     0

5.4 while-Schleifen

Bei einer while-Schleife muß nicht von Anfang an feststehen, wie oft eine Schleife durchlaufen wird. Vor jedem Durchlauf wird eine logische Schleifenbedingung abgeprüft, ist diese wahr, so wird die Schleife ein weiteres mal durchlaufen, anderenfalls wird sie abgebrochen. Im Schleifenkörper muß der Wert der Schleifenbedingung beeinflußt werden, da sie anderenfall unendlich oft durchlaufen würde. While-Schleifen haben in Matlab die Form:

   while Schleifenbedingung
      Schleifenkörper
   end
Zu beachten ist, daß jeder numerische Wert außer 0 in der Schleifenbedingung als 'wahr' gewertet wird, das gilt auch für Inf. Dagegen werden [] als 'falsch' gewertet und NaN führt zu einer Fehlermeldung.
    x=1;
    q=(x^2-3)/(2*x);
    while abs(q) > 1.0e-8
       x = x -q;
       q = (x^2-3)/(2*x);
     end
    [x q x^2]
   ans =
       1.7321    0.0000    3.0000
 while []
    1
  end
 while NaN
    1
  end
  ??? IF or WHILE condition is NaN

5.5 break-Anweisung

Bei einer einfachen Schleife wiederholt sich der Ablauf:
  • Schleifenbedingung prüfen
  • Schleifenkörper abarbeiten
solange, bis die Schleifenbedingung nicht mehr erfüllt ist. Zusätzliche Abbruchkriterien kann man in einer Schleife mittels if-Abfrage und der break-Anweisung formulieren. Die break-Anweisung beendet die Abarbeitung des Schleifenkörpers der innersten Schleife.
    n=1; m=1;
    while n < 5
      while m < 5
         m=m+1
         if m==3
            break
         end
      end
      'in der aeusseren Schleife'
      n=n+1;
   end
   m =
        2
   m =
        3
   ans =
   in der aeusseren Schleife
   m =
        4
   m =
        5
   ans =
   in der aeusseren Schleife
   ans =
   in der aeusseren Schleife
   ans =
   in der aeusseren Schleife
    for n=2:6
         fk=1;
         for k=2:n
            fk=fk*k;
            if fk > 50
               break
            end
         end
         [ n fk ]
      end
   ans =
        2     2
   ans =
        3     6
   ans =
        4    24
   ans =
        5   120
   ans =
        6   120

Beispiel 5.5:

Berechnung einer Nullstelle des Polynoms:
p(x) = x^3 - 2*x -5
Es ist bekannt, daß der Wert von p(1) negativ und der von p(3) positiv ist. Es wird eine Nullstelle im Intervall (links=1,rechts=3) gesucht. Die Bisection wird solange durchgeführt, wie die Intervall-Länge 'rechts - links' noch größer eps*rechts ist. Der Wert von rechts liegt zwischen 1 und 3, der Wert von eps*rechts wird daher nicht 0 und die Bisection wird nach endlich vielen Schritten beendet.

   links  = 1; fl = -inf;
   rechts = 3; fr = +inf;
   while rechts-links > eps*rechts
      mitte = (links+rechts)/2;
      fm    = mitte^3 - 2*mitte - 5;
      if fm == 0
         break
      elseif sign(fm) == sign(fl)
         links = mitte;
         fl    = fm;
      else
         rechts = mitte;
         fr     = fm;
      end
   end
   mitte
Als Ergebnis liefert Matlab:
   mitte =
      2.0946