2013-01-02 13 views
8

Eventuali duplicati:
Python rounding error with float numbers
python maths is wrongErrore Python nella sottrazione di base?

non posso ottenere Python per fare correttamente la sottrazione 1-0,8 e assegnarlo. Continua a fornire la risposta errata, 0.19999999999999996.

ho esplorato un po ':

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

e scoperto che questo errore si verifica con un gruppo alquanto casuale dei galleggianti tra 0 e 1 alla terza cifra decimale. Un errore simile si verifica anche quando si quadrano i float, ma in un sottoinsieme diverso.

Spero di avere una spiegazione di questo e di come fare in modo che Python esegua l'aritmetica. L'utilizzo di round(x,3) è l'aggiramento che sto usando per ora, ma non è elegante.

Grazie!

Si tratta di una sessione nel mio 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 
>>> 

Ecco il codice che ho messo in un paio interpreti on-line:

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

print doit() 

e l'uscita:

{'a': 0.19999999999999996} 
+3

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

+0

http://effbot.org/pyfaq/why-are -calcoli a punto di virata-così-inaccurati.htm –

risposta

8

I numeri in virgola mobile non funzionano come ci si aspetta.

Per i principianti, leggere floating point guide. Per farla breve: i computer rappresentano numeri in virgola mobile come binari e si scopre che non è possibile memorizzare una frazione decimale precisa come binario (try it for yourself su carta per capire perché). Ai fini pratici, 0,19999999999999996 è "abbastanza vicino" a 0,2. Se si voleva stamparlo come 0.2, allora si potrebbe fare qualcosa di simile:

print "%0.1f" % floating_point_value 

Quindi quello che stai vedendo non è un errore. È un comportamento previsto.

+0

Grazie. A proposito, l'output di doit() è un dizionario, non un intero, quindi 'print"% 0.1f "% doit()' non funziona in questo caso. – gotube

+0

Hai ragione. Ho aggiornato la risposta per essere un po 'più esplicita. – misha

1

Python memorizza i float con "bit", mentre alcuni galleggiano semplicemente non possono rappresentare in modo accurato, non importa quanti bit di precisione si abbiano. Questo è il problema che hai qui. È come cercare di scrivere 1/3 in decimale con una quantità limitata di decimali posti perfettamente accurati.

8

Usa Decimal la sua progettata proprio per questo:

>>> 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