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! :lol:

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. :D

Gruss wuf :wink:

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