Seite 1 von 1
Problem mit Countdown
Verfasst: Samstag 20. September 2008, 00:22
von bremer
Code: Alles auswählen
from time import time
zaehler = int(raw_input("Geben Sie die Anzahl der Sekunden an: "))
zeitpunkt = time()
diff, grenze = 0, 0
while diff < zaehler: # Solange die Differenz kleiner als die vorgegebene Anzahl der Sekunden ist.
diff = time() - zeitpunkt # diff = bisher vergangene Zeit.
if diff >= grenze: # Immer wenn die bisher vergangene Zeit groesser als die derzeitige Grenze ist.
print zaehler - grenze
grenze += 0.1
Ich bekomme als letzten Wert dann manchmal so kryptische Werte wie "1.11022302463e-16"
Kann mir jemand erklären, wie das zu Stande kommt?
Verfasst: Samstag 20. September 2008, 01:25
von nuss
Hmm, ich habs mal umgeschrieben, mit dem gleichen ergebniss,
würde mich auch mal interressieren, warum dabei zum schluss so ein komischer wert rauskommt, obwohl man mit gefixten werten arbeitet.
P.s so musst du nicht so viel mit differenzen und so arbeiten
Code: Alles auswählen
#!/usr/bin/python
from time import sleep
import sys
spanne = int(sys.argv[1])
diff = 0.1
def countdown(spanne, diff):
spanne -= diff
print spanne
return spanne
while spanne >= 0:
sleep(diff)
spanne = countdown(spanne, diff)
edit: ich hab das mal in ner ganz normalen while schleife probiert,
mit dem gleichen ergebniss. Scheint ein interpreter-fehler zu sein.
Verfasst: Samstag 20. September 2008, 07:30
von sma
Floats sind prinzipbedingt ungenau. Lebe mit den Abweichungen, benutze
decimal oder rechne mit (genauen) Ganzzahlen (int) und teile dann erst das Ergebnis zur Anzeige. Das sind deine Möglichkeiten.
Das ganze liegt daran, dass Computer Zahlen im Binärsystem repräsentieren und es keine exakte Repräsentation von 0.1 gibt, wenn man nur 1/2, 1/4, 1/8, usw. als Brüche zur Verfügung hat.
Steht auch im Tutorial.
Stefan
Verfasst: Samstag 20. September 2008, 07:31
von BlackJack
1.11022302463e-16 ist kein kryptischer Wert, sondern eine Zahl, die ganz nahe an Null dran ist. Das liegt daran, das zum Beispiel 10 mal 0.1 aufaddiert nicht 1 ist sondern:
Code: Alles auswählen
In [51]: sum([0.1] * 10)
Out[51]: 0.99999999999999989
In [52]: 1 - sum([0.1] * 10)
Out[52]: 1.1102230246251565e-16
Das wiederum ist kein Fehler von Python sondern die normale Rechenungenauigkeit mit der man bei Fliesskommazahlen in jeder Programmiersprache rechnen muss.
Verfasst: Samstag 20. September 2008, 07:32
von numerix
nuss hat geschrieben:Scheint ein interpreter-fehler zu sein.
Sicher!
Hier wird mit Fließkommazahlen gearbeitet. Aufgrund der ganz normalen Ungenauigkeiten bei diesem Zahlentyp ist der letzte Wert nicht exakt Null, sondern nur fast Null, nämlich z.B. ca. 10^-16, das ist fast Null.
Verfasst: Samstag 20. September 2008, 09:34
von jens
Würde so gehen:
Code: Alles auswählen
from time import sleep
import sys
spanne = int(sys.argv[1])
diff = 0.1
def countdown(spanne, diff):
spanne -= diff
print round(spanne,2)
return spanne
while spanne-diff > 0:
sleep(diff)
spanne = countdown(spanne, diff)
Die Bedingung bei while war auch falsch.
Verfasst: Samstag 20. September 2008, 10:11
von numerix
Ich hätte es so gemacht:
Code: Alles auswählen
from time import sleep
dauer = float(raw_input("Dauer: "))
while abs(dauer)>0.001:
dauer -= 0.1
print "%2.1f" %abs(dauer)
sleep(0.1)
@Jens: Deine Abbruchbedingung funktioniert nicht immer korrekt. Je nachdem, ob der letzte Wert knapp über oder unter Null liegt, wird die "0.0" noch ausgegeben oder eben nicht.
Verfasst: Samstag 20. September 2008, 11:19
von rayo
Hi
Warum nicht ganz weg von diesen Floats?
Code: Alles auswählen
from time import sleep
duration = float(raw_input("Dauer: "))
step_size = 0.1
steps = int(duration/step_size)
while steps > 0:
print "%2.1f" % (steps*step_size)
steps -= 1
sleep(step_size)
Gruss
Verfasst: Samstag 20. September 2008, 11:24
von jens
Dann könnte man auch von den while Schleife weg:
Code: Alles auswählen
from time import sleep
duration = float(raw_input("Dauer: "))
step_size = 0.1
steps = int(duration/step_size)
for count in xrange(steps):
sleep(step_size)
print count, step_size*count+step_size
Verfasst: Samstag 20. September 2008, 13:17
von wuf
Hallo Forumfreunde
Ich finde die Varianten von 'rayo' und 'jens' auch die richtigen Lösungsanstätze um das Floating-Problem in den Griff zu bekommen. (Do it with integers)
Übrigens die Variante von 'jens' müsste als 'count up' bezeichnet werden.
Gruss wuf
Verfasst: Samstag 20. September 2008, 13:27
von jens
btw. eigentlich schade, das man nicht
range(0, duration, step_size) machen kann. Da die Funktion gern integer Werte haben möchte
Mal selber machen:
Code: Alles auswählen
from time import sleep
def xrange2(start, stop, step=1.0):
duration = stop - start
steps = int(duration/step)
for count in xrange(steps):
yield step_size*count+step_size
duration = float(raw_input("Dauer: "))
step_size = 0.1
for no in xrange2(0, duration, step_size):
sleep(step_size)
print no