2013-01-02 10 views
8

Mögliche Duplizieren: - 0,8 und weisen Sie
Python rounding error with float numbers
python maths is wrongPython-Fehler in der grundlegenden Subtraktion?

Ich kann Python nicht richtig die Subtraktion 1 erhalten zu tun. Es kommt immer wieder auf die falsche Antwort, 0.19999999999999996.

erforschten I ein Bit:

sq = {} 
sub = {} 
for i in range(1000): 
    sq[str(i/1000.)+'**2']=((i/1000.)**2) 
    sub['1-'+str(i/1000.)]=(1.0-(i/1000.)) 

und entdecken, dass dieser Fehler mit einer etwas zufälligen Gruppe des Schwimmer zwischen 0 und 1 auf die dritte Dezimalstelle passiert. Ein ähnlicher Fehler tritt auch auf, wenn Sie diese Floats quadrieren, aber zu einer anderen Teilmenge.

Ich hoffe auf eine Erklärung dafür und wie Python die Rechenkünsten richtig machen. Die Verwendung von round(x,3) ist das Workaround, das ich gerade benutze, aber es ist nicht elegant.

Danke!

Dies ist eine Sitzung in meinem Python 2.7.3 Shell:

*** Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32. *** 
*** Remote Python engine is active *** 
>>> 1-0.8 
0.19999999999999996 
>>> print 1-0.8 
0.2 
>>> a = 1-0.8 
>>> a 
0.19999999999999996 
>>> print a 
0.2 
>>> a = 0.2 
>>> print a 
0.2 
>>> a 
0.2 
>>> 

Hier ist der Code, den ich in ein paar online gestellt Dolmetscher:

def doit(): 
    d = {'a':1-0.8} 
    return d 

print doit() 

und die Ausgabe:

{'a': 0.19999999999999996} 
+3

Scheck http://www.yoda.arachsys.com/csharp/floatingpoint.html – avasal

+0

http://effbot.org/pyfaq/why-are -floating-point-Berechnungen-so-ungenau.htm –

Antwort

8

Floating-Nummern funktionieren nicht so, wie Sie es erwarten.

Für den Anfang lesen Sie die floating point guide. Lange Rede, kurzer Sinn: Computer stellen Fließkommazahlen als binär dar, und es stellt sich heraus, dass es nicht möglich ist, einen genauen Dezimalbruch als Binärwert zu speichern (try it for yourself auf dem Papier, um zu sehen, warum). Für praktische Zwecke ist 0,19999999999999996 "nahe genug" zu 0,2. Wenn Sie es als 0.2 drucken wollte, dann könnte man so etwas wie:

print "%0.1f" % floating_point_value 

Also, was Sie sehen, ist kein Fehler. Es ist erwartetes Verhalten.

+0

Danke. Übrigens, die Ausgabe von doit() ist ein Dictionary, keine ganze Zahl, also 'print"% 0.1f "% doit()' funktioniert in diesem Fall nicht. – gotube

+0

Sie haben Recht. Ich habe die Antwort aktualisiert, um etwas expliziter zu sein. – misha

1

Python speichert schwebt mit "Bits", und einige Schwimmer können Sie einfach nicht genau darstellen, egal wie viele Bits der Präzision Sie haben. Dies ist das Problem, das Sie hier haben. Es ist so, als würde man versuchen, 1/3 im Dezimalformat mit einer begrenzten Anzahl von Dezimalstellen genau zu schreiben.

8

Verwenden Decimal seine speziell dafür:

>>> from decimal import Decimal, getcontext 
>>> Decimal(1) - Decimal(0.8) 
Decimal('0.1999999999999999555910790150') 
>>> getcontext().prec = 3 
>>> Decimal(1) - Decimal(0.8) 
Decimal('0.200') 
>>> float(Decimal(1) - Decimal(0.8)) 
0.2