Die while-Schleife und die repeat-Schleife in R

Die while-Schleife und die repeat-Schleife sind etwas allgemeiner als die for-Schleife. Wenn man wei├č, wie oft eine Schleife durchlaufen werden soll, ist die for-Schleife weniger fehleranf├Ąllig einzusetzen. Ist dagegen nur die Bedingung bekannt, unter die Schleife verlassen werden soll, muss man die while- oder repeat-Schleife einsetzen. Die while-Schleife realisiert die kopfgesteuerte Schleife, die repeat-Schleife besitzt keine Bedingungspr├╝fung. Wie bei der for-Schleife k├Ânnen die Schl├╝sselw├Ârter break (vorzeitiges Verlassen der Schleife) und next (sofortiger ├ťbergang zum n├Ąchsten Schleifen-Durchlauf) eingesetzt werden.
Noch keine Stimmen abgegeben
Noch keine Kommentare

Einordnung des Artikels

Viele der Bezeichnungen aus Die for-Schleife in R werden hier ebenfalls verwendet, ohne sie erneut einzuf├╝hren. F├╝r Leser, die zum ersten Mal mit Schleifen konfrontiert werden, wird daher empfohlen, vor diesem Kapitel Die for-Schleife in R durchzuarbeiten.

Einf├╝hrung

Arten von Schleifen

In der Einf├╝hrung zu Die for-Schleife in R wurden die drei Arten von Schleifen kurz vorgestellt:

  • die kopfgesteuerte Schleife,
  • die fu├čgesteuerte Schleife und
  • die Schleife mit Z├Ąhlvariable.

Die Schleife mit Z├Ąhlvariable (for-Schleife) wurde dort ausf├╝hrlich besprochen; die kopfgesteuerte und die fu├čgesteuerte Schleife werden in diesem Kapitel erl├Ąutert.

Die Unterschiede dieser Schleifen k├Ânnen jetzt schon benannt werden:

  1. Bei der Schleife mit Z├Ąhlvariable muss schon vor Betreten der Schleife bekannt sein, wie viele Durchl├Ąufe stattfinden werden, da in der for-Anweisung der Vektor angegeben wird, ├╝ber den iteriert wird. (Streng genommen ist diese Aussage nicht ganz richtig, da man mit Hilfe von break die Schleife vorzeitig verlassen kann.)
  2. Die kopfgesteuerte und die fu├čgesteuerte Schleife sind allgemeiner als die Schleife mit Z├Ąhlvariable, da sie durch eine Bedingungspr├╝fung gesteuert werden: Ist die Bedingung erf├╝llt, wird die Schleife nochmals ausgef├╝hrt. Im Allgemeinen kann man daher nicht immer voraussagen, wie oft die Schleife durchlaufen wird. Sie kann sogar unendlich oft durchlaufen werden; man spricht dann von einer nicht terminierenden Schleife.
  3. Umgekehrt kann aber jede for-Schleife in eine kopfgesteuerte oder fu├čgesteuerte Schleife umformuliert werden. Oft ist es eine reine Geschmacksfrage, welche Art der Schleife gew├Ąhlt wird.

Die kopfgesteuerte und die fu├čgesteuerte Schleife im Pseudocode

Wie die kopfgesteuerte und die fu├čgesteuerte Schleife durch eine Bedingungspr├╝fung vor beziehungsweise nach dem Schleifenk├Ârper gesteuert wird, kann wieder am Paradebeispiel "Personalien aufnehmen" demonstriert werden (siehe Die for-Schleife in R und Abbildung 1, 2):

Abbildung 1: Die kopfgesteuerte Schleife zum Aufnehmen der Personalien von N Personen. Ob die Schleife durchlaufen werden muss oder ob sie ├╝bersprungen wird, entscheidet sich vor dem Durchlauf der Schleife. Bei jedem Durchlauf verringert sich die Anzahl der Personen, die noch abgearbeitet werden m├╝ssen, daher die Anweisung N = N - 1.Abbildung 1: Die kopfgesteuerte Schleife zum Aufnehmen der Personalien von N Personen. Ob die Schleife durchlaufen werden muss oder ob sie ├╝bersprungen wird, entscheidet sich vor dem Durchlauf der Schleife. Bei jedem Durchlauf verringert sich die Anzahl der Personen, die noch abgearbeitet werden m├╝ssen, daher die Anweisung N = N - 1.

Abbildung 2: Die fu├čgesteuerte Schleife zum Aufnehmen der Personalien von N Personen. Im Unterschied zur kopfgesteuerten Schleife werden jetzt zuerst die Personalien einer Person aufgenommen und dann erst wird abgefragt, ob die Schleife nochmals durchlaufen werden muss. Wie oben verringert sich bei jedem Durchlauf die Anzahl der Personen, die noch abgearbeitet werden m├╝ssen, daher wieder die Anweisung N = N - 1.Abbildung 2: Die fu├čgesteuerte Schleife zum Aufnehmen der Personalien von N Personen. Im Unterschied zur kopfgesteuerten Schleife werden jetzt zuerst die Personalien einer Person aufgenommen und dann erst wird abgefragt, ob die Schleife nochmals durchlaufen werden muss. Wie oben verringert sich bei jedem Durchlauf die Anzahl der Personen, die noch abgearbeitet werden m├╝ssen, daher wieder die Anweisung N = N - 1.

Im Pseudocode ÔÇô jetzt allgemein und nicht mehr f├╝r das spezielle Beispiel ÔÇô w├╝rde man die Schleifen aus den Abbildungen 1 und 2 wie folgt realisieren:

# kopfgesteuerte Schleife:

solange (Bedingung)
    wiederhole (Anweisung)
# fu├čgesteuerte Schleife:

wiederhole (Anweisung)
    bis (Bedingung)

Realisierung in R

Die Realisierung der kopfgesteuerten und fu├čgesteuerten Schleife geschieht in R mit folgenden Konstrukten:

# kopfgesteuerte Schleife:

while(cond) expr

# fu├čgesteuerte Schleife:

repeat expr

Man beachte, dass die kopfgesteuerte Schleife genau den Pseudocode umsetzt, dagegen unterscheidet sich die fu├čgesteuerte Schleife vom Pseudocode:

  1. Bei der kopfgesteuerten Schleife wird zun├Ąchst eine Bedingung cond gepr├╝ft; ist sie erf├╝llt, wird der Anweisungs-Block expr ausgef├╝hrt. Anschlie├čend wird erneut die Bedingung gepr├╝ft und so weiter. Erst wenn die Bedingung cond gleich FALSE ist, wird die Schleife verlassen.
  2. Bei der fu├čgesteuerten Schleife wird sofort der Anweisungs-Block expr ausgef├╝hrt. Ist er abgearbeitet, wird er erneut ausgef├╝hrt und so weiter. Im Gegensatz zur Formulierung im Pseudocode besitzt die repeat-Schleife keine Bedingungspr├╝fung und wird daher im Normalfall als Endlos-Schleife ausgef├╝hrt. Um sie zum Anhalten zu bringen, muss man eine break-Anweisung einf├╝gen.

Die folgenden Abschnitte geben einige Beispiele f├╝r die while- und die repeat-Schleife.

Die while-Schleife

Die while-Schleife als Ersatz f├╝r eine for-Schleife

Im Kapitel ├╝ber die for-Schleife wurde mehrmals das Beispiel angef├╝hrt, wie die Zahlen von 1 bis 100 addiert werden. Dieses Problem l├Ąsst sich auch mit einer while-Schleife l├Âsen, im n├Ąchsten Unterabschnitt wird aber gezeigt, dass dies nicht der typische Einsatz von while ist.

Das Beispiel aus Die for-Schleife in R zum Addieren der Zahlen lautete:

idx <- (1:100)
summe <- 0

for(i in idx){
  summe <- summe + i
}

cat("Summe: ", summe, "\n")
# Summe:  5050

Eine gleichwertige Realisierung mit einer while-Schleife k├Ânnte wie folgt aussehen:

i <- 1
summe <- 0

while(i < 101){
    summe <- summe + i
    i <- i + 1
}

cat("Summe: ", summe, "\n")
# Summe:  5050

Zeile 1 und 2: Es werden die beiden Variablen i (Z├Ąhlvariable) und summe vorbereitet; in summe werden die Zwischensummen abgespeichert, am Ende enth├Ąlt summe die Summe der Zahlen von 1 bis 100.

Zeile 4 bis 7: Die while-Schleife mit der Bedingungspr├╝fung in den runden Klammern und dem Schleifenk├Ârper in den geschweiften Klammern.

Im Schleifenk├Ârper wird die Summe gebildet, indem zum aktuellen Wert der Zwischensumme der aktuelle Wert von i addiert wird (Zeile 5). Und die Z├Ąhlvariable i wird um 1 erh├Âht (Zeile 6).

Ist die Bedingung in den runden Klammern (Zeile 4) gleich TRUE, werden die Anweisungen des Schleifenk├Ârpers ausgef├╝hrt. M├Âchte man daher bis i = 100 summieren, muss die Bedingung lauten i < 101 ; denn sobald i == 101 erreicht ist, wird der Schleifenk├Ârper nicht mehr ausgef├╝hrt, die Schleife verlassen und es erfolgt die cat()-Anweisung aus Zeile 9.

Vergleicht man die for-Schleife mit der entsprechenden while-Schleife, sollte sofort klar sein, dass die Konfiguration der for-Schleife weniger fehleranf├Ąllig ist: bei der while-Schleife muss man sich sowohl bei der Initialisierung als auch bei der Beendigung der Schleife Gedanken machen, ob die Variablen die richtigen Werte besitzen; bei der for-Schleife sind die Werte der Variablen leichter nachvollziehbar.

Der typische Einsatz einer while-Schleife

Das Beispiel oben sollte nur zeigen, dass eine for-Schleife immer durch eine while-Schleife ersetzt werden kann. Es beschreibt nicht den typischen Anwendungsfall einer while-Schleife. Denn oftmals wei├č man nicht im Voraus, wie oft eine Schleife durchlaufen werden soll, sondern man kennt nur die Bedingung, wann sie verlassen werden soll. Dies ist etwa der Fall, wenn ein Nutzer eines Programmes immer neue Zahlen eingibt, die verarbeitet werden sollen und die Eingabe zu einem Ende kommt, wenn anstelle einer Zahl ein vereinbartes Zeichen eingegeben wird. Jetzt kann man den Abbruch der Schleife nur ├╝ber die Bedingung formulieren und nicht durch einen vorgegebenen Vektor, den man schon vor den Nutzer-Eingaben setzen m├╝sste.

Ein anderes typisches Beispiel f├╝r eine while-Schleife zeigt die folgende Fragestellung: Es sollen solange die Zahlen 1, 2, 3, ... addiert werden, bis ihre Summe eine gewisse Grenze ├╝berschreitet. Ohne die Formel f├╝r die Summe

1 + 2 + 3 + ... + n = n ┬Ě (n+1)/2

kann man nicht voraussagen, wie viele Summanden es gibt, bis die Grenze erreicht wird. Aber das Problem kann mit Hilfe einer while-Schleife erledigt werden ÔÇô ohne die entsprechende Formel zu verwenden. Das folgende Skript zeigt eine m├Âgliche Realisierung mit der Grenze 1000:

i <- 1
summe <- 0

while(summe < 1000){
    summe <- summe + i
    i <- i + 1
}

cat("Summe: ", summe, "\n")
# Summe:  1035
cat("Index: ", i, "\n")
# Index:  46

# Kontrolle
sum(1:45)
# [1] 1035

Das Skript zeigt aber auch, dass es im Vergleich zur for-Schleife schwieriger ist nachzuvollziehen, welche Werte die Variablen beim Verlassen der Schleife haben. Hier k├Ânnen sich leicht Fehler einschleichen und daher soll das Skript ausf├╝hrlich beschrieben werden ÔÇô insbesondere welche Befehle beim letzten Durchlauf der Schleife noch abgearbeitet werden. Dem Programmier-Anf├Ąnger wird dringend empfohlen, dies immer im Trockentest nachzupr├╝fen.

Zeile 1 und 2: Wie oben werden die beiden Variablen i (Z├Ąhlvariable) und summe vorbereitet.

Zeile 4 bis 7: Im Schleifenk├Ârper der while-Schleife wird:

  • die Summe gebildet (Zeile 5),
  • die Z├Ąhlvariable i um 1 erh├Âht (Zeile 6).

Der Schleifen-Durchlauf wird wiederholt, solange summe kleiner ist als 1000 (Zeile 4).

An der Kontroll-Ausgabe (Zeile 15 und 16) erkennt man, dass

1 + 2 + 3 + ... + 45 = 1035.

Mit diesem Wissen ist es leichter nachzuvollziehen, wie die Schleife verlassen wird:

Nachdem die Schleife mit i = 44 durchlaufen wurde, ist summe = 990 und i wird auf 45 erh├Âht. Hier sieht man, wie wichtig die Reihenfolge der Anweisungen im Schleifenk├Ârper ist: Bei einer Vertauschung von Zeile 5 und 6 ergibt sich ein anderes Verhalten.

Da summe < 1000 erf├╝llt ist, wird die Schleife nochmals durchlaufen: Jetzt wird summe = 990 + 45 berechnet, was 1035 ergibt. Und i wird auf 46 erh├Âht.

Da jetzt die Bedingung summe < 1000 gleich FALSE ist, wird der Schleifenk├Ârper nicht mehr aufgerufen und die Schleife verlassen. Die Variablen i und summe besitzen somit die Werte i = 46 und summe = 1035.

Gefragt war aber nach der Summe der Zahlen von 1 bis n, so dass die Summe noch kleiner ist als 1000. Daf├╝r muss man wieder zu i = 44 und summe = 990 aus dem vorletzten Schleifen-Durchlauf zur├╝ckgehen:

1 + 2 + 3 + ... + 44 = 990.

Die folgende Aufgabe soll verdeutlichen, wie wichtig es ist, die Werte der Variablen beim Betreten und Verlassen der while-Schleife zu kennen.

Aufgabe: F├╝hren sie diesen Trockentest durch, wenn im Skript oben die Zeilen 5 und 6 vertauscht werden:

  1. Welche Werte haben i und summe beim ersten und zweiten Durchlauf der Schleife?
  2. Welche Werte haben i und summe nach dem Verlassen der Schleife?

Die Schl├╝sselw├Ârter break und next

Im Kapitel Die for-Schleife in R wurde im Abschnitt Die Schl├╝sselw├Ârter break und next erkl├Ąrt, wie man break und next zur zus├Ątzlichen Steuerung der Schleife einsetzen kann:

  1. Die Anweisung break sorgt daf├╝r, dass die Schleife vorzeitig verlassen wird.
  2. Die Anweisung next sorgt daf├╝r, dass der folgende Teil des Schleifenk├Ârpers ├╝bersprungen wird und der n├Ąchste Schleifen-Durchlauf startet.

Diese beiden Schl├╝sselw├Ârter haben in der while-Schleife dieselbe Bedeutung wie in der for-Schleife und werden nicht nochmals erl├Ąutert.

Die repeat-Schleife

In der Einf├╝hrung wurde schon darauf hingewiesen, dass die repeat-Schleife nicht realisiert, was man im Pseudocode als fu├čgesteuerte Schleife bezeichnet; auch in vielen anderen Programmiersprachen ist die repeat-Schleife als fu├čgesteuerte Schleife realisiert. Dagegen hat sie in R keine Bedingungspr├╝fung und f├╝hrt daher eigentlich zu einer Endlos-Schleife.

Beim Einsatz der repeat-Schleife ist daher vom Programmierer darauf zu achten, dass keine Endlos-Schleife entsteht. Dazu wird eine Bedingungspr├╝fung eingebaut, die eine break-Anweisung enth├Ąlt. Das folgende Skript zeigt ein Beispiel:

n <- 2

repeat {
  n <- n^2
  if(!is.finite(n)) break
  cat(n, "\n")
}

# 4 
# 16 
# 256 
# 65536 
# 4294967296 
# 1.844674e+19 
# 3.402824e+38 
# 1.157921e+77 
# 1.340781e+154

Die repeat-Schleife ist in den Zeilen 3 bis 7 enthalten.

L├Ąsst man Zeile 5 weg, wird die Zahl n (ausgehend von n = 2) in jedem Schleifen-Durchlauf quadriert; sobald der Zahlenbereich f├╝r double ├╝berschritten wird, wird f├╝r n der "Wert" Inf ausgegeben.

In Zeile 5 wird daf├╝r gesorgt, dass die Schleife verlassen wird, wenn n den Zahlenbereich ├╝berschreitet.

Das folgende Skript zeigt die Berechnung der Summe der nat├╝rlichen Zahlen 1 + 2 + ... bis zur Schranke 1000 f├╝r die Summe ÔÇô jetzt realisiert mit einer repeat-Schleife:

i <- 1
summe <- 0

repeat{
  summe <- summe + i
  i <- i + 1
  if(summe > 1000) break
}
 
cat("Summe: ", summe, "\n")
# Summe:  1035
cat("Index: ", i, "\n")
# Index:  46

Aufgabe:

Versuchen Sie wieder im Trockentest nachzuvollziehen, welche Werte i und summe haben, wenn die Schleife verlassen wird.

Zusammenfassung

while-Schleife

while(cond) expr

Solange die Bedingung cond gleich TRUE ist, wird der Anweisungs-Block expr ausgef├╝hrt. Ist cond gleich FALSE, wird die Schleife verlassen.

Zus├Ątzlich kann die Schleife mit Hilfe von break und next gesteuert werden.

repeat-Schleife

repeat expr

Der Anweisungs-Block expr wird beliebig oft ausgef├╝hrt. Zur Steuerung muss zus├Ątzlich eine break-Anweisung verwendet werden.

Wie bei der for-Schleife und bei der while-Schleife ist zus├Ątzlich der Einsatz der next-Anweisung m├Âglich.

Weitere Informationen ├╝ber while-Schleifen und repeat-Schleifen findet man in der Dokumentation unter ?Control im Paket base.