@anniika_s00: Beide Fehlermeldungen weisen ja recht deutlich darauf hin, dass sich ``break`` und ``continue`` in einer Schleife befinden müssen. Denn die beiden Anweisungen beziehen sich ja darauf eine Schleife abzubrechen oder sofort den nächsten Schleifendurchlauf zu beginnen.
Was da also fehlt ist die ”Endlosschleife”, die den ganzen Code den Du geschrieben hast, enthält. Und dann haben die beiden ``continue``-Anweisungen keinen Effekt. Die kann man weg lassen, ohne das sich am Programmablauf etwas ändert. Das ist auch gut so, denn ``continue`` sollte man vermeiden und kann man in der Regel auch leicht vermeiden.
`a`, `b`, und `erg` sind keine guten Namen. Man kürzt Namen nicht kryptisch ab, die sollen doch dem Leser vermitteln was der Wert dahinter bedeutet. Wenn man `ergebnis` meint, sollte man das auch schreiben. Ausserdem sollte man Namen erst definieren wenn man sie braucht. Zwischen der Initialisierung von `b` und `erg` und dem Code der dann tatsächlich etwas damit macht, liegen nicht nur viele Zeilen Code, sondern es ist auch überhaupt noch nicht klar ob die beiden Variablen überhaupt benutzt werden.
Wenn der Benutzer eine ganze Zahl eingeben muss, warum wandelst Du die Eingabe dann mit `float()` in einen Dezimalbruch um? Und nicht gleich mit `int()` in eine ganze Zahl? Denn auch bei `float()` muss man den `ValueError` behandeln der entsteht wenn der Benutzer etwas eingibt das nicht in eine Gleitkommazahl umgewandelt werden kann.
Dann brauchst Du auch diesen komplizierten Ausdruck nicht: ``(a - int(a)) == 0) is False``. Da ist als erstes mal das ``is False`` falsch. Das macht man nicht. Der Ausdruck dafür ist ja bereits ein Wahrheitswert und bei dem ``is``-Vergleich kommt nur wieder ein Wahrheitswert heraus. Und zwar das Gegenteil von dem Wahrheitswert des Ausdrucks vor dem ``is``. Das kann man aber mit ``not`` bekommen: ``not a - int(a) == 0``. Das ``not`` kann man sich sparen in dem man die Vergleichsbedingung umdreht: ``a - int(a) == 0``. Aber wie ich in der Antwort an Jankie schon schrieb: `a.is_integer()`. Da braucht man dann auch keinen Kommentar mehr der Erklärt warum der Code das macht was der da macht. Ist aber alles sowieso nicht nötig wenn man die Eingabe gleich in eine ganze Zahl wandelt, denn dann braucht man nicht mehr darauf testen.
Das Du da mehrfach im Code das einlesen von `a` stehen hast ist auch falsch. Erstens wandelst Du die Zeichenkette da gar nicht in eine Zahl um, und zweitens kann der Benutzer dabei doch auch wieder Fehler machen oder eine 0 eingeben.
Den Fall mit dem Abbruch des Programms würde ich nach der Eingabe als erstes behandeln. Das sollte so geschrieben sein, dass man möglichst deutlich erkennt was da passiert.
Bei der Fakultät sollte man die laufende Zahl von 1 bis `zahl` laufen lassen, nihct von 0 bis `zahl - 1` und dann bei der Rechnung immer unnötigerweise +1 rechnen müssen. Also statt:
Code: Alles auswählen
i = 0
ergebnis = 1
while i < zahl:
ergebnis *= i + 1
i += 1
besser:
Code: Alles auswählen
i = ergebnis = 1
while i <= zahl:
ergebnis *= i
i += 1
Wobei das ganz klar ein Fall für eine ``for``-Schleife ist:
Code: Alles auswählen
ergebnis = 1
for i in range(1, zahl + 1):
ergebnis *= i + 1
Beziehungsweise für `functools.reduce()`:
Code: Alles auswählen
from functools import reduce
from operator import mul
...
ergebnis = reduce(mul, range(1, zahl + 1), 1)
Oder halt gleich `math.factorial()`.
Wenn man `print()` so verwendet wie Du das verwendest, dann ist zwischen der Zahl und dem "!" ein Leerzeichen, und auch vor dem Satzende. Man formatiert die Werte am besten in *eine* Zeichenkette und gibt die dann aus.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
from math import factorial
def main():
while True:
try:
zahl = int(input("Bitte eine ganze positive Zahl: "))
except ValueError:
print("Die Zahl muss eine ganze Zahl sein!")
else:
if zahl == 0:
print("Das Spiel ist zu Ende!")
break
try:
ergebnis = factorial(zahl)
except ValueError:
print("Die Zahl muss positiv sein!")
else:
print(f"Das Ergebnis von {zahl}! ist {ergebnis}.")
if __name__ == "__main__":
main()