Seite 1 von 2
Rechnen mit "float(str(Zahl)" ?
Verfasst: Donnerstag 27. Juli 2006, 15:42
von Leto
Hallo,
ich habe eine seltsame "Entdeckung" gemacht, die erfahrenen Programmieren in Python wahrscheinlich bekannt sein dürfte.
Da ich mich gerade mit der Ungenauigkeit von Python float's herumschlagen muss - Stichwort:
- bin ich ganz zufällig auf folgende Lösung dieses Problems gestoßen:
Wie kommt das? Warum geht das eine, das andere aber nicht. Rechenfehler bleibt doch Rechenfehler.
Verfasst: Donnerstag 27. Juli 2006, 16:05
von pyStyler
Hi,
also bei mir sieht die Rechnung so aus
Code: Alles auswählen
>>> float (0.3-0.1) == 0.19999999999999998
True
#float 0.2 ist in python
>>> float(0.2)
0.20000000000000001
vlt hilft dir das ein bisschen.
Verfasst: Donnerstag 27. Juli 2006, 16:07
von helmut
Gestrichen, da hatte ich Addition und Subtraktion vertauscht.
Gruss, Helmut
Verfasst: Donnerstag 27. Juli 2006, 17:32
von Leto
Also mir ist schon klar, dass (0.3-0.1) und 0.2 in Python nicht gleich sind.
ich verstehe nur nicht, warum str(0.3-0.1) auf einmal '0.2' ist.
Wird da gerundet? Und wenn ja, an welcher Stelle bzw. nach welchem System?
Verfasst: Donnerstag 27. Juli 2006, 17:45
von DatenMetzgerX
Code: Alles auswählen
>>> round(0.3-0.1, 1)
0.20000000000000001
>>> round(0.3-0.1, 1) == 0.2
True
So geht es

Verfasst: Donnerstag 27. Juli 2006, 18:01
von pyStyler
Leto hat geschrieben:Also mir ist schon klar, dass (0.3-0.1) und 0.2 in Python nicht gleich sind.
ich verstehe nur nicht, warum str(0.3-0.1) auf einmal '0.2' ist.
Wird da gerundet? Und wenn ja, an welcher Stelle bzw. nach welchem System?
vielleicht ist es so besser .
Code: Alles auswählen
>>> a=str(0.3-0.1)
>>> b=0.2
>>> a == b
False
>>> print float(a)
0.2
>>> float(a) == b
True
weisst du jetzt was da passiert ist ?
Im übrigen es wird nirgends wo gerundet ( nur mal als hilfe )!Den Rest musst du selber rausfinden

Verfasst: Donnerstag 27. Juli 2006, 19:26
von birkenfeld
Um hier mal Klarheit zu schaffen:
Floats sind nicht nur in Python ungenau. Sie sind überall ungenau, weil das nicht anders geht, wenn man dezimale Zahlen in einem Binärsystem mit einer begrenzten Anzahl von Stellen repräsentiert. (Deswegen gibts ja auch das decimal-Modul).
Bei Anwendung von str() auf einen float wird auf 12 Stellen, bei repr() auf 17 Stellen "gerundet". Eventuelle Nullen am Ende werden dann entfernt. Das führt dazu, dass die Ausgabe von
>>> 0.3-0.1
0.1999...
anders aussieht als von
>>> print 0.3-0.1
0.2
da print str() verwendet, das Prompt an sich aber repr().
Verfasst: Donnerstag 27. Juli 2006, 20:11
von pyStyler
Hi birkenfeld
birkenfeld hat geschrieben:
Bei Anwendung von str() auf einen float wird auf 12 Stellen, bei repr() auf 17 Stellen "gerundet". Eventuelle Nullen am Ende werden dann entfernt. Das führt dazu, dass die Ausgabe von
weiss nicht so genau was du damit meinst !
Code: Alles auswählen
>>> x=float(0.2)
>>> y=str(0.2)
>>> x
0.20000000000000001
>>> y
'0.2'
>>> float(y)
0.20000000000000001
>>>
Verfasst: Donnerstag 27. Juli 2006, 20:19
von DatenMetzgerX
Code: Alles auswählen
>>> str(0.3)
'0.3'
>>> repr(0.3)
'0.29999999999999999'
str() entfernt die überflüssigen 0s und rundet zuerst noch
Verfasst: Donnerstag 27. Juli 2006, 20:44
von pyStyler
DatenMetzgerX hat geschrieben:Code: Alles auswählen
>>> str(0.3)
'0.3'
>>> repr(0.3)
'0.29999999999999999'
str() entfernt die überflüssigen 0s und rundet zuerst noch
sorry aber das ist so nicht ganz richtig.
Code: Alles auswählen
>>> x=str(0.3)
>>> type(x)
<type 'str'>
>>> y=float(x)
>>> type(y)
<type 'float'>
>>>
>>> x
'0.3'
>>> y
0.29999999999999999
>>>
Verfasst: Donnerstag 27. Juli 2006, 20:57
von birkenfeld
pyStyler hat geschrieben:DatenMetzgerX hat geschrieben:Code: Alles auswählen
>>> str(0.3)
'0.3'
>>> repr(0.3)
'0.29999999999999999'
str() entfernt die überflüssigen 0s und rundet zuerst noch
sorry aber das ist so nicht ganz richtig.
Doch, man kann es so sagen.
pyStyler hat geschrieben:
Code: Alles auswählen
>>> x=str(0.3)
>>> type(x)
<type 'str'>
>>> y=float(x)
>>> type(y)
<type 'float'>
>>>
>>> x
'0.3'
>>> y
0.29999999999999999
>>>
Was soll das jetzt beweisen? Indem du float("0.3") ausführst, hast du wieder einen Float. Keinen String. Wenn du diesen am Interpreterprompt direkt anzeigen lässt (also via repr()), wird die Ungenauigkeit deutlich. Nochmal:
Es gibt keine Möglichkeit für den Computer, die 0.3 als Float exakt zu speichern.
Verfasst: Donnerstag 27. Juli 2006, 21:16
von pyStyler
hmm ich will hier nichts beweisen! Nur bitte ich den Unterschied zwischen einen String und einer Dezimalzahl zumachen.
Verfasst: Donnerstag 27. Juli 2006, 21:17
von birkenfeld
pyStyler hat geschrieben:hmm ich will hier nichts beweisen! Nur bitte ich den Unterschied zwischen einen String und eine Dezimalzahl zumachen.
Das ist ja auch löblich. Nur war das doch gar nicht das Thema.
Verfasst: Donnerstag 27. Juli 2006, 21:19
von pyStyler
birkenfeld hat geschrieben:pyStyler hat geschrieben:hmm ich will hier nichts beweisen! Nur bitte ich den Unterschied zwischen einen String und eine Dezimalzahl zumachen.
Das ist ja auch löblich. Nur war das doch gar nicht das Thema.
naja wie auch immer ... Fakt ist das hier ein paar infos nicht ganz richtig waren.
Verfasst: Donnerstag 27. Juli 2006, 21:20
von birkenfeld
pyStyler hat geschrieben:naja wie auch immer ... Fakt ist das hier ein paar infos nicht ganz richtig waren.
Solange jetzt nicht die meinst, auf die du mit "weiss nicht so genau was du damit meinst !" geantwortet hast...

Verfasst: Donnerstag 27. Juli 2006, 21:22
von pyStyler
meinst du vlt das hier >>> print float(a)
Verfasst: Donnerstag 27. Juli 2006, 21:25
von birkenfeld
Ohne Zusammenhang ist das für mich bedeutungslos.
Verfasst: Freitag 28. Juli 2006, 08:15
von Leto
Sorry, aber noch hab ich nichts gerafft.
Das sind mir doch ein paar Aussagen zu viel (und scheinbar so widersprüchlich).
1. Mir ist schon klar, warum eine Zahl wie 0.3 binär nicht exakt dargestellt werden kann.
2. Mir ist auch klar warum das für z.b für 0.5 geht.
3. Mir ist ebenso klar, dass durch diese Ungenauigkeit ein Rechenfehler bei '0.3-01' auftritt, so dass das Ergebnis ungleich 0.2 ist.
4. Mir war nur eben nicht klar, warum str(0.3-0-1) auf einmal '0.2' ist.
Gut scheinbar wird da gerundet (das mit dem 'Nullen wegstreichen' war ja wohl überflüssig, immerhin reden wir von floatingpoint und nicht von fixedpoint).
Nur nach welchem System? An welcher Kommastelle? Woher weiß Python denn, wann gerundet werden soll und wann eine Zahl wie 0.19999999999999998 das tatsächlich erwartete Ergebnis darstellt?
Verfasst: Freitag 28. Juli 2006, 09:14
von Rebecca
Code: Alles auswählen
>>> str(0.123456789123456789123456789)
'0.123456789123'
str rundet immer auf die gleiche Anzahl Nachkommastellen genau (nach obigem Beispiel scheinen es 12 Nachkommastellen zu sein).
Code: Alles auswählen
>>> 0.3
0.29999999999999999
>>> str(0.29999999999999999)
'0.3'
0.29999999999999999 auf 12 Stellen gerundet ist nunmal 0.300000000000 (wenn ich mich jetzt nicht verzaehlt habe). str() ist dann noch so schlau, die ueberfluessigen Nullen am Ende wegzulassen.
D.h. Python weiss ueberhaupt nichts von "exakt". Fuer den Computer sind diese Maschinenzahlen alle exakt.
Verfasst: Freitag 28. Juli 2006, 12:34
von Leto
Na jetzt hab ichs (hoffentlich).
Wär mal interessant zu wissen, warum str denn an der 12 Stelle kürzt. Gibt es dafür irgendeinen logischen/technischen Hintergrund?