2010-06-06 15 views
10

jestem rodzaju mylić dlaczego python dodać dodatkową liczbę dziesiętną w tym przypadku, proszę mi pomóc wyjaśnićpyton pływających numer

>>> mylist = ["list item 1", 2, 3.14] 
>>> print mylist ['list item 1', 2, 3.1400000000000001] 
+0

+1 do zadawania inteligentne pytanie, nie zakładając, że był to błąd w Pythonie. –

+1

Podobne do http://stackoverflow.com/questions/2880547/python-rounding-problem –

+2

możliwy duplikat [Dlaczego dziesiętne liczby nie mogą być dokładnie odwzorowane w systemie binarnym?] (Http: // stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represent-exact-in-binary) –

Odpowiedz

13

Liczby zmiennoprzecinkowe są wartościami przybliżonymi, nie mogą przechowywać liczby dziesiętne dokładnie. Ponieważ starają się reprezentować bardzo duży zakres liczb tylko w 64 bitach, muszą one w pewnym stopniu być zbliżone.

Bardzo ważne jest, aby być tego świadomym, ponieważ powoduje to pewne dziwne efekty uboczne. Na przykład możesz rozsądnie myśleć, że suma dziesięciu partii 0.1 będzie wynosiła 1.0. Choć wydaje się to logiczne, ale także źle, jeśli chodzi o zmiennoprzecinkowych:

>>> f = 0.0 
>>> for _ in range (10): 
... f += 0.1 
... 
>>> print f == 1.0 
False 
>>> f 
0.99999999999999989 
>>> str(f) 
1.0 

Można by pomyśleć, że n/m * m == n. Po raz kolejny, zmiennoprzecinkową świat nie zgadza:

>>> (1.0/103.0) * 103.0 
0.99999999999999989 

A może tak dziwnie, jeden może pomyśleć, że dla wszystkich n, n + 1 != n. W zmiennoprzecinkowych ziemię, numery po prostu nie działają tak:

>>> 10.0**200 
9.9999999999999997e+199 
>>> 10.0**200 == 10.0**200 + 1 
True 
# How much do we have to add to 10.0**200 before its 
# floating point representation changes? 
>>> 10.0**200 == 10.0**200 + 10.0**183 
True 
>>> 10.0**200 == 10.0**200 + 10.0**184 
False 

Zobacz What every computer scientist should know about floating point numbers za doskonałe podsumowanie zagadnień.

Jeśli potrzebujesz dokładnej reprezentacji dziesiętnej, sprawdź moduł decimal, będący częścią standardowej biblioteki Pythona od wersji 2.4. Pozwala określić liczbę znaczących cyfr. Wadą jest to, że jest znacznie wolniejsza niż zmiennoprzecinkowa, ponieważ operacje zmiennoprzecinkowe są realizowane w sprzęcie, podczas gdy operacje dziesiętne odbywają się wyłącznie w oprogramowaniu. Ma również własne problemy z niedokładnością, ale jeśli potrzebujesz dokładnej reprezentacji liczb dziesiętnych (np. Dla aplikacji finansowej), jest to idealne rozwiązanie.

Na przykład:

>>> 3.14 
3.1400000000000001 
>>> import decimal 
>>> decimal.Decimal('3.14') 
>>> print decimal.Decimal('3.14') 
3.14 
# change the precision: 
>>> decimal.getcontext().prec = 6 
>>> decimal.Decimal(1)/decimal.Decimal(7) 
Decimal('0.142857') 
>>> decimal.getcontext().prec = 28 
>>> decimal.Decimal(1)/decimal.Decimal(7) 
Decimal('0.1428571428571428571428571429') 
+0

>>> z decimal import * Traceback (najgłębszy ostatni): Plik "", wiersz 1, w? ImportError: Brak modułu o nazwie dziesiętnej Wystąpił błąd podczas próby importowania modułu dziesiętnego, gdzie mogę go uzyskać? może to zabrzmieć głupio, ale jestem nowy w python. – user359925

+0

dziesiętny jest dostępny z wersji Pythona 2.4 i późniejszych. –

+2

@zhack, jesteśmy społecznością programistów odpowiadającą na pytania bez żadnych korzyści. Przestańcie mówić, że wasze pytania są głupie. – Warty

0

Jak wspomniano wcześniej, to wszystko o zmiennym punktów będących przybliżeniem.

Jeśli chcesz dokładnością można użyć po przecinku (co jest dokładna reprezentacja): http://docs.python.org/library/decimal.html

a = [1.5, 1.49999] 
a 
[1.5, 1.4999899999999999] 

from decimal import Decimal 
b = [1.5, Decimal('1.4999')] 
b 
[1.5, Decimal('1.4999')] 
+0

Należy pamiętać, że wiele aplikacji niefinansowych NIE POTRZEBUJE dokładności. A funkcje takie jak 'sin',' ln' i 'sqrt' nie zwracają dokładnych odpowiedzi w żadnej bazie. – dan04

6

Warto zauważyć, że Python 3.1 ma nową procedurę wyjścia zmiennoprzecinkowej że jest zaokrąglany w tym w oczekuje sposób (to zostało również przeniesione do Python 2.7):

Python 3.1 (r31:73572, Aug 15 2009, 17:12:41) 
[GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> a = [3.14] 
>>> print(a) 
[3.14] 

z dokumentu What's New in Python 3.1:

Python now uses David Gay’s algorithm for finding the shortest floating point representation that doesn’t change its value. This should help mitigate some of the confusion surrounding binary floating point numbers.

The significance is easily seen with a number like 1.1 which does not have an exact equivalent in binary floating point. Since there is no exact equivalent, an expression like float('1.1') evaluates to the nearest representable value which is 0x1.199999999999ap+0 in hex or 1.100000000000000088817841970012523233890533447265625 in decimal. That nearest value was and still is used in subsequent floating point calculations.

-1

Możemy go naprawić za pomocą tego polecenia:

>>> x = 1.2 - 1.0 
>>> x 
0.19999999999999996 
>>> y = float(str(x)) 
>>> y 
0.2 

dodam odpowiedź od @mark