ein freies Lehrmittel auf der Basis von eduskript

Solange-Schleifen: while

Lernziele
  • Sie verstehen, wie Sie mit while eine Schleife erstellen können, die solange läuft, wie eine Bedingung True ist.
  • Sie können mit einer while-Schleife zählen und die kleinste Zahl finden, die eine bestimmte Bedingung erfüllt.
  • Sie können mit break eine Schleife vorzeitig beenden.
  • Sie haben repetiert, wie man mit input() Benutzereingaben abfragen und mit int() in Zahlen umwandeln kann.

Nun schauen wir uns die while-Schleife an. Das ist eine Schleife, die ihren Körper wiederholt, solange eine bestimmte Bedingung wahr ist. Das ist sinnvoll, wenn Sie im Vornherein nicht wissen, wie oft etwas getan werden soll.

Beginnen wir gleich mit dem Beispiel im letzten Teil. Wir suchten da die kleinste Zahl ii, die alle diese Bedingungen erfüllt:

  • imod113=1i \mod{113} = 1
  • imod213=2i \mod{213} = 2
  • imod313=3i \mod{313} = 3

Die Lösung haben wir gefunden, indem wir bei der for-Schleife manuell den Zahlenbereich schrittweise erhöht haben. Das ist natürlich sehr unpraktisch — und genau das löst die while-Schleife!

Syntax

while Bedingung:
    # Code, der ausgeführt wird, solange die Bedingung wahr ist

Zählen mit while

Zur Veranschaulichung beginnen wir mit einem Beispiel, das ähnlich einer for-Schleife von 0 bis 9 zählt.

Loading editor...

Beachten Sie folgende Aspekte:

  • Für den Codeblock gilt die typische Syntax: Ein Doppelpunkt schliesst den Kopf des Blocks ab, der Einzug links definiert, was zur Schleife gehört.
  • Die Bedingung der while-Schleife wird wie bei if-Statements geschrieben.
  • Die Bedingung wird nur zu Beginn einer Iteration überprüft. Wenn die Bedingung True ist, wird der gesamte Körper der Schleife wiederholt. Das sehen Sie beim letzten "Schluss der Iteration", das ausgeführt wird, obwohl i bereits den Wert 10 hat und die Bedingung nicht mehr erfüllt.

Predict-then-Verify: Off-by-one!

Ein häufiger Fehler bei while-Schleifen ist das sogenannte "Off-by-one"-Problem (um eins daneben). Überlegen Sie kurz, was am Ende dieses Programms ausgegeben wird:

k = 5
while k <= 7:
    k += 1
print("Fertig:", k)

Beispiele

Elegante Lösung, um kleinste Zahl zu finden

Kehren wir damit nochmal zur Aufgabe aus dem letzten Teil zurück. Unsere Lösung war:

for i in range(10000000):
    if i % 113 == 1 and i % 213 == 2 and i % 313 == 3:
        print(i, "restlose Zahl")

Jetzt mit while-Schleife lassen wir das einfach laufen, solange wir die Zahl nicht gefunden haben. Sobald wir die Zahl gefunden haben, wiederholt sich die Schleife nicht mehr — und i ist unsere gesuchte Zahl!

i = 0
while not (i % 113 == 1 and i % 213 == 2 and i % 313 == 3):
    i += 1
print(i, "restlose Zahl")

Die einzelnen Teilbedingungen der while-Schleife könnten Sie auch ausklammern.

# "Solange die gesamte Bedingung nicht erfüllt ist", ist logisch dasselbe wie...
not (i % 113 == 1 and i % 213 == 2 and i % 313 == 3)
# "Solange eine der Bedingungen nicht erfüllt ist"
i % 113 != 1 or i % 213 != 2 or i % 313 != 3

Endlosschleife mit while

Eine Endlosschleife ist eine while-Schleife, die nie endet. Das passiert, wenn die Bedingung immer wahr ist.

while True:
    print("Das ist eine Endlosschleife!")

Das ist eine Endlosschleife, die verlässlich immer wieder "Das ist eine Endlosschleife!" ausgibt. Um sie zu beenden, müssen Sie das Programm entweder manuell stoppen (z.B. mit Ctrl/Strg + C in der Konsole) oder das Schlagwort break verwenden. Ein weiteres Beispiel:

while True:
    eingabe = input("Geben Sie eine Zahl ein (oder 'exit' zum Beenden): ")
    if eingabe == "exit":
        break
    else:
        print(f"Sie haben die Zahl {eingabe} eingegeben.")

Wann ist eine Endlosschleife sinnvoll? Bei echten Computerprogrammen eher selten. Aber bei kleinen Robotern oder Microcontrollern, die immer dasselbe tun sollten, solange sie Strom haben, kann eine Endlosschleife unter Umständen sinnvoll sein.

Bug-Hunt: Der Summen-Hänger

Hier wollte jemand die Summe aller Zahlen von 1 bis n berechnen. Für n=10 sollte 55 herauskommen, aber das Programm liefert nur 10. Finden und korrigieren Sie den Fehler. Tipp: Die Schleife läuft schon korrekt — schauen Sie genau, was im Schleifenkörper mit total passiert.

Loading editor...

Challenge: Collatz-Folge

Die Collatz-Folge ist eines der berühmtesten ungelösten Probleme der Mathematik. Die Regel ist denkbar einfach: Sie starten bei einer beliebigen positiven Zahl n und wiederholen folgende Schritte, bis Sie bei 1 ankommen:

  • Ist n gerade, halbieren Sie es: n = n // 2
  • Ist n ungerade, rechnen Sie: n = 3 * n + 1

Niemand weiss bis heute, ob diese Folge wirklich für jede Startzahl irgendwann bei 1 endet — aber empirisch klappt es bisher immer.

Auto-Grading

Schreiben Sie eine Funktion collatz_schritte(n), die die Anzahl Schritte zurückgibt, die nötig sind, bis aus n eine 1 wird. Die while-Schleife ist hier perfekt: Sie wissen vorher nicht, wie lange es dauert!

Loading editor...
Mögliche Lösung
def collatz_schritte(n):
    schritte = 0
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
        schritte += 1
    return schritte

Beachten Sie: Die while-Bedingung ist n != 1 — wir laufen, solange wir noch nicht angekommen sind. Sobald n == 1, bricht die Schleife ab und wir geben die gezählten Schritte zurück.

Aufgabe: Ein Ratespiel entwickeln mit while

Im folgenden Beispiel entwickeln wir ein kleines Ratespiel. Der Computer denkt sich eine Zahl zwischen 1 und 100 aus, und der Spieler muss sie erraten. Der Computer gibt dem Spieler Hinweise, ob die geratene Zahl zu hoch oder zu niedrig ist.

Pseudocode

Die Idee etwas genauer in Pseudocode gefasst:

Zufallszahl zwischen 1 und 100 ziehen
Solange die Zahl nicht erraten wurde
    Eingabe abfragen
    Wenn die Zahl zu hoch ist:
        Hinweis geben: "Zu hoch!"
    Wenn die Zahl zu niedrig ist:
        Hinweis geben: "Zu niedrig!"
Hinweis geben: "Gratuliere!"

Zufallszahlen ziehen

Um eine Zufallszahl zu ziehen, verwenden wir die Funktion randint aus dem Modul random. Diese Funktion zieht eine ganze Zahl zwischen zwei Werten (inklusive der beiden Werte). Wir importieren das Modul mit dem Befehl import random.

import random
# Zufallszahl zwischen 1 und 100
zahl = random.randint(1, 100)
print(zahl)

Input abfragen

Um den Spieler nach einer Zahl zu fragen, verwenden wir die Funktion input. Diese Funktion gibt den eingegebenen Text als String zurück. Um ihn in eine Ganzzahl umzuwandeln, verwenden wir die Funktion int.

# Eingabe abfragen
eingabe = input("Gib eine Zahl zwischen 1 und 100 ein: ")
# Eingabe von Zeichenkette/String in Ganzzahl/Integer umwandeln
zahl = int(eingabe)
print(zahl)

Erklärvideo

Mögliche Lösung
import random

# Generiere eine Zufallszahl zwischen 1 und 100
geheimzahl = random.randint(1, 100)

# Variablen für das Spiel initialisieren
versuchsrunde = 0
geratete_zahl = -1

# Begrüssung und Spielerklärung
print("Willkommen zum Zahlenratespiel!")
print("Ich habe mir eine Zahl zwischen 1 und 100 ausgedacht.")

# Solange die Zahl nicht erraten wurde, weiterspielen
while geratete_zahl != geheimzahl:
    eingabe = input("Rate eine Zahl zwischen 1 und 100: ")
    geratete_zahl = int(eingabe)
    versuchsrunde += 1

    # Prüfen, ob die geratene Zahl korrekt ist
    if geratete_zahl < geheimzahl:
        print("Zu niedrig! Versuch es mit einer höheren Zahl.")
    elif geratete_zahl > geheimzahl:
        print("Zu hoch! Versuch es mit einer niedrigeren Zahl.")

# Wenn die Zahl erraten wurde, gratulieren
# Hint: Wir nutzen hier einen sogenannten f-String, um Variablen in Strings einzufügen,
#       Sie könnten natürlich auch den String mit '+' verketten oder mit Kommas getrennt drucken.
#       f-Strings sind eine moderne Möglichkeit, die Ihnen viele Formatierungsprobleme lösen wird.
print(f"Gratuliere! Du hast die Zahl {geheimzahl} in {versuchsrunde} Versuchen erraten!")

Zusammenfassung

Zusammenfassung

while-Schleife

Eine while-Schleife wiederholt ihren Körper, solange eine Bedingung True ist. Im Gegensatz zur for-Schleife müssen Sie nicht im Voraus wissen, wie viele Iterationen nötig sind — perfekt, wenn Sie auf ein Ereignis warten oder so lange suchen, bis Sie etwas finden.

while Bedingung:
    # Code, der wiederholt wird

Drei klassische while-Bugs

  • Vergessenes Update: Wenn keine Variable in der Bedingung verändert wird, läuft die Schleife endlos. Sorgen Sie immer dafür, dass die Bedingung irgendwann False wird.
  • Falsches Update: Wie im Bug-Hunt — total = i statt total += i schreibt jeden Schritt einfach den letzten Wert in die Variable, statt aufzubauen.
  • Off-by-one: Die Bedingung wird vor jedem Durchlauf geprüft, nicht danach. Eine Schleife mit while i <= 7 läuft auch noch, wenn i gleich 7 ist — und erhöht i dann auf 8.

break und Endlosschleifen

Mit while True: bauen Sie eine Endlosschleife, die Sie mit break verlassen. Das ist nützlich, wenn das Abbruchkriterium innerhalb der Schleife liegt — z.B. nach Benutzereingabe (Ratespiel) oder beim Treffen einer Bedingung mitten im Körper.

while True:
    eingabe = input("Eingabe (oder 'exit'): ")
    if eingabe == "exit":
        break
    # ... sonst weiterverarbeiten

Wann for, wann while?

  • for wenn die Anzahl Iterationen vorher feststeht (eine Liste durchgehen, eine Range zählen).
  • while wenn das Ende von einer Bedingung abhängt (auf etwas warten, bis zu einem Ereignis suchen).