Seite 1 von 1
Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 17:34
von Alkatar
Hallo hier im Forum,
in meiner freien Zeit versuche ich mir aktuell Python beizubringen. Dazu habe ich mir das Buch "Einstieg in Python" von Thomas Theis zugelegt. Damit komme ich bisher auch erstaunlich gut zurecht. Heute bin ich allerdings an einer Übung hängen geblieben. Es geht um ein einfaches Rechenspiel:
Code: Alles auswählen
# Zufallsgenerator
import random
random.seed()
# Werte und Berechnung
a = random.randint(1,10)
b = random.randint(1,10)
c = a + b
print("Die Aufgabe:", a, "+", b)
# Eingabe
print("Bitte eine Zahl eingeben:")
z = input()
zahl = int(z)
# Mehrfache Verzweigung, logische Operatoren
# Bedingungen mit mehreren Vergleichsoperatoren
if zahl == c:
print(zahl, "ist richtig")
elif zahl < 0 or zahl > 100:
print(zahl, "ist ganz falsch")
elif c-1 <= zahl <= c+1:
print(zahl, "ist ganz nahe dran")
else:
print(zahl, "ist falsch")
# Ende
print("Ergebnis: ", c)
Das Rechenspiel funktioniert auch wunderbar. Was ich allerdings nicht ganz nachvollziehen kann, ist der folgende Vergleich:
Code: Alles auswählen
elif c-1 <= zahl <= c+1:
print(zahl, "ist ganz nahe dran")
Dieser Vergleich ist dann wahr, wenn die eingegebene Zahl nur um 1 daneben liegt. Aber egal wo ich nachschaue, steht als Bedeutung für den Vergleichsoperator <= der Satz "kleiner als
oder gleich". Das muss aber doch auch bedeuten, wenn die Aufgabe 5 + 3 lautet und ich 6 eingebe, der Vergleich dennoch wahr ist, oder? Denn 6 ist kleiner als 8. Die Ausgabe lautet aber "6 ist falsch".
In meiner Lösung hatte ich den Vergleich so umgesetzt:
Code: Alles auswählen
elif c-1 or c+1 == zahl:
print(zahl, "ist ganz nahe dran")
Kann mir jemand dabei helfen, zu erklären, warum der Vergleich im Buch funktioniert bzw. wo mein Denkfehler ist? Da wäre ich sehr dankbar.
Viele Grüße
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 18:18
von nezzcarth
Vielleicht hilft es, das auszuschreiben. Für dein Beispiel würde da ja dann stehen:
Code: Alles auswählen
7 <= 6 <= 9
oder etwas umfomuliert
(6 >= 7) and (9 >= 6)
Es sollte denke ich unmittelbar klar sein, dass das falsch ist. Die Auswertung erfolgt von Links nach Rechts und 7 ist nicht kleiner oder gleich 6. Zulässige Werte wären 7,8 und 9.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 19:29
von Alkatar
Alles klar, da hatte ich einen ordentlichen Knoten im Kopf. Das Aufschreiben hat sehr gut geholfen. Ich habe es so gemacht:
Falsch (mit der Zahl 6):
Code: Alles auswählen
wenn (6 größer oder gleich 7 ist) und (9 größer oder gleich 6 ist)
Wahr (mit der Zahl 7):
Code: Alles auswählen
wenn (7 größer oder gleich 7 ist) und (9 größer oder gleich 7 ist)
Falsch (mit der Zahl 8):
Code: Alles auswählen
wenn (8 größer oder gleich 7 ist) und (9 größer oder gleich 8 ist)
Wahr (mit der Zahl 9):
Code: Alles auswählen
wenn (9 größer oder gleich 7 ist) und (9 größer oder gleich 9 ist)
Zulässige Werte sind dann also nur 7 und 9. Besten Dank für das schnelle aufknoten! :-)
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 20:02
von nezzcarth
Fast
Alkatar hat geschrieben:
Falsch (mit der Zahl

:
Code: Alles auswählen
wenn (8 größer oder gleich 7 ist) und (9 größer oder gleich 8 ist)
8 Ist doch größer als 7 und 9 ist größer als 8. Insofern gehört die 8 mit in die Aufzählung der zulässigen Werte.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 21:32
von BlackJack
Wobei ich das komisch umgeschrieben finde, denn eigentlich sollte man das so umschreiben das man nichts an den Operatoren ändert:
Code: Alles auswählen
# a op1 b op2 c → a op1 b and b op2 c
7 <= 6 <= 9 → 7 <= 6 and 6 <= 9
Dokumentiert ist das in der Referenzdokumentation unter
Comparisons.
@Alkatar: Der `random.seed()`-Aufruf ist überflüssig und kann unter Umständen sogar für weniger ”Zufall” sorgen.
Die Grenzen auf die in Zeile 21 in Deinem ersten Beitrag geprüft wird sind ziemlich willkürlich und könnten sogar falsch sein wenn man die Grenzen für die Zufallszahlen ändert. Es ist an solchen Stellen sicherer wenn man keine festen Zahlen verwendet, sondern die berechnet, mit Hilfe der Zahlen von denen diese Grenze(n) letztlich ja abhängen.
Dein Ansatz das als ``c-1 or c+1 == zahl`` zu schreiben ist falsch, denn das ist immer ”wahr”, nur in dem Fall das `c` den Wert 1 hat nicht. Was aber mit den Grenzen für die Zufallszahlen nicht passieren kann, also ist diese Bedingung dann *immer* ”wahr”. ``or`` ist ein binärer Operator, kein umgangssprachliches „oder“. Was dort steht ist explizit geklammert äquivalent zu ``(c-1) or (c+1 == zahl)``. Das heisst entweder c-1 muss ”wahr” sein, oder c+1 == zahl muss ”wahr” sein. Alle Zahlen ausser die 0 sind ”wahr”, das heisst der erste Operand vom ``or`` ist bereits immer ”wahr” weil `c` nie den Wert 1 annehmen kann, was der einzige Wert wäre an dem der Wert des ersten Operanden 0, also ”unwahr” werden kann.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 21:49
von nezzcarth
@BlackJack: Ich habe es bewusst zusätzlich zum 'and' auch mit veränderten Operatoren umgeschrieben, um die andere Variante zu haben, falls das Verständnis-Problem dort liegt. So hat man finde ich einen Überblick über den Gesamtzusammenhang.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Samstag 26. August 2017, 23:41
von Alkatar
nezzcarth hat geschrieben:Fast
Alkatar hat geschrieben:
Falsch (mit der Zahl

:
Code: Alles auswählen
wenn (8 größer oder gleich 7 ist) und (9 größer oder gleich 8 ist)
8 Ist doch größer als 7 und 9 ist größer als 8. Insofern gehört die 8 mit in die Aufzählung der zulässigen Werte.
Amen! Harter Tag heute
BlackJack hat geschrieben:@Alkatar: Der `random.seed()`-Aufruf ist überflüssig und kann unter Umständen sogar für weniger ”Zufall” sorgen.
Ok, im Buch wird der Aufruf so begründet:
Der Aufruf der Funktion seed() des Moduls random führt dazu, dass der Zufallszahlengenerator mit der aktuellen Systemzeit initialisiert wird. Anderenfalls könnte es passieren, dass anstelle einer zufälligen Auswahl immer wieder die gleichen Zahlen geliefert würden.
BlackJack hat geschrieben:Die Grenzen auf die in Zeile 21 in Deinem ersten Beitrag geprüft wird sind ziemlich willkürlich und könnten sogar falsch sein wenn man die Grenzen für die Zufallszahlen ändert. Es ist an solchen Stellen sicherer wenn man keine festen Zahlen verwendet, sondern die berechnet, mit Hilfe der Zahlen von denen diese Grenze(n) letztlich ja abhängen.
Das kann ich nachvollziehen. Fairerweise sollte ich aber noch erwähnen, dass das oben genannte Rechenspiel aus dem Buch nicht das Endergebnis ist, sondern die ersten Schritte dahin. Ich denke, Zeile 21 dient hier mehr der Veranschaulichung einer Mehrfach-Verzweigung und wird schon bald wieder aus dem Rechenspiel verschwinden.
BlackJack hat geschrieben:Dein Ansatz das als ``c-1 or c+1 == zahl`` zu schreiben ist falsch, denn das ist immer ”wahr”, nur in dem Fall das `c` den Wert 1 hat nicht. Was aber mit den Grenzen für die Zufallszahlen nicht passieren kann, also ist diese Bedingung dann *immer* ”wahr”. ``or`` ist ein binärer Operator, kein umgangssprachliches „oder“. Was dort steht ist explizit geklammert äquivalent zu ``(c-1) or (c+1 == zahl)``. Das heisst entweder c-1 muss ”wahr” sein, oder c+1 == zahl muss ”wahr” sein. Alle Zahlen ausser die 0 sind ”wahr”, das heisst der erste Operand vom ``or`` ist bereits immer ”wahr” weil `c` nie den Wert 1 annehmen kann, was der einzige Wert wäre an dem der Wert des ersten Operanden 0, also ”unwahr” werden kann.
Ich sehe schon, ich habe noch einiges vor mir

Vielen Dank für die Hinweis!
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Sonntag 27. August 2017, 08:27
von BlackJack
@Alkatar: Die Erklärung zu `random.seed()` ist falsch, da hat der Autor wohl Erfahrungen mit einer anderen Programmiersprache auf Python übertragen. Es werden nicht immer die gleichen Zahlen geliefert, auch ohne das man diese Funktion aufruft, und genau der Teil mit der Systemzeit kann zu Problemen führen. *Das* macht zumindest CPython $GOTT sei Dank mittlerweile auch nicht mehr wenn das System eine bessere Quelle für Entropie hat als die Systemzeit.
`random.seed()` ist nur *mit* Argument wirklich sinnvoll, nämlich dann wenn man absichtlich die gleiche Zahlenfolge haben möchte. Beispielsweise in Dokumentation, damit Doctests funktionieren, oder für Benchmarks oder Unit-Tests, wenn man zufällige, aber wiederholbare Folgen von Zahlen benötigt.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Montag 28. August 2017, 20:10
von darktrym
Die Erklärung von seed ist durchaus richtig. Mit seed wird der Initialisierungsvektor neu gebildet ob vom Betriebssystem über libc sei mal dahingestellt. Andersfalls liefert der Pseudozufallsgenerator in der Tat irgendwann die gleichen Zahlen wenn nicht hart für neue Entropie gesorgt wird.
Re: Verständnisfrage Vergleichsoperatoren
Verfasst: Montag 28. August 2017, 20:38
von BlackJack
@darktrym: Nein die Beschreibung ist falsch. Und Deine Erklärung ist auch mindestens irreführend. Fakt ist, das ein `seed()`-Aufruf ohne Argument keinen Gewinn bringt, da wird nichts zufälliger. Aber umgekehrt unter bestimmten Umständen `seed()`-Aufrufe ohne Argument für *weniger* zufällige Zahlen sorgen können. Bei CPython mittlerweile nicht mehr sofern das System eine gute Zufallsquelle hat, aber trotzdem sollte man den Leuten diese Voodoo-Aufrufe abgewöhnen, die nur weiterleben weil das irgend wann einmal bei anderen Sprachen nötig war.
Was passieren kann ist das sich die Pseudozufallsfolge irgendwann wiederholt. Allerdings ist die Periode 2**19937-1. Das sollte also kein Problem darstellen.
Die `libc` hat damit nichts zu tun. Das klingt wieder nach ”altem” Wissen, das auf Python so nicht anwendbar ist.