2013-01-02 14 views
8

Powiel możliwe:
Python rounding error with float numbers
python maths is wrongBłąd w języku Python w podstawowym odejmowaniu?

nie mogę Python, aby poprawnie zrobić odejmowania 1 - 0,8 i przypisać ją. Nadchodzi z nieprawidłową odpowiedzią, 0.19999999999999996.

ja zbadałem trochę:

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

i odkrył, że ten błąd ma miejsce z nieco przypadkowej grupy pływaków między 0 i 1 do trzeciego miejsca po przecinku. Podobny błąd występuje również, gdy wyrównasz te zmienne, ale w innym podzbiorze.

Mam nadzieję, że wyjaśnienie tego i jak sprawić, aby Python zrobił arytmetykę dobrze. Używanie round(x,3) jest rozwiązaniem, którego obecnie używam, ale nie jest eleganckie.

Dzięki!

Jest to sesja w moim 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 
>>> 

Oto kod umieścić w kilku tłumaczy forum:

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

print doit() 

i wyjście:

{'a': 0.19999999999999996} 
+3

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

+0

http://effbot.org/pyfaq/why-are - obliczenia punktowe-tak-inaccurate.htm –

Odpowiedz

8

Liczby zmiennoprzecinkowe nie działają zgodnie z oczekiwaniami.

Na początek przeczytaj floating point guide. Krótko mówiąc: komputery reprezentują liczby zmiennoprzecinkowe jako binarne i okazuje się, że zapisanie dokładnej ułamka dziesiętnego jako binarnej nie jest możliwe (try it for yourself na papierze, aby zobaczyć dlaczego). Dla celów praktycznych 0.19999999999999996 jest "wystarczająco blisko" do 0.2. Jeśli chcesz wydrukować go jako 0.2, możesz zrobić coś takiego:

print "%0.1f" % floating_point_value 

To, co widzisz, nie jest błędem. To oczekiwane zachowanie.

+0

Dzięki. BTW, wyjście doit() jest słownikiem, a nie liczbą całkowitą, więc 'print"% 0.1f "% doit()' nie działa w tym przypadku. – gotube

+0

Masz rację. Zaktualizowałem odpowiedź, by była nieco bardziej wyraźna. – misha

1

Magazyny w Pythonie są unoszone za pomocą "bitów", a niektóre pływaki, których nie można dokładnie przedstawić, bez względu na to, ile masz dokładności. To jest problem, który tutaj masz. To tak jakby próbować napisać 1/3 w systemie dziesiętnym z ograniczoną liczbą miejsc dziesiętnych idealnie dokładnie.

8

Zastosowanie Decimal produkty przeznaczone tylko dla tego:

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