2010-06-06 15 views
10

Ich bin ein bisschen verwirrt, warum Python einige zusätzliche Dezimalzahl in diesem Fall hinzufügen, helfen Sie bittePython-Float-Zahl

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

+1 für eine intelligente Frage zu stellen, nicht, dass dies ein Fehler in Python war angenommen wird. –

+1

Ähnlich wie http://stackoverflow.com/questions/2880547/python-rounding-problem –

+2

mögliche Duplikate von [Warum können Dezimalzahlen nicht genau in Binär dargestellt werden?] (Http: // stackoverflow.com/questions/1089018/why-cant-decimal-numbers-dargestellt-genau-in-binär) –

Antwort

13

Gleitkommazahlen sind eine Annäherung zu erklären, können sie Dezimalzahlen nicht speichern genau. Weil sie versuchen, einen sehr großen Zahlenbereich in nur 64 Bits darzustellen, müssen sie sich in gewissem Maße annähern.

Es ist sehr wichtig, sich dessen bewusst zu sein, denn es führt zu einigen seltsamen Nebenwirkungen. Zum Beispiel könnten Sie vernünftigerweise annehmen, dass die Summe von zehn Losen 0.11.0 wäre. Während dies logisch erscheint, ist es auch falsch, wenn es um Fließkomma kommt:

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

Sie, dass n/m * m == n vielleicht denken. Wieder einmal Gleitkommazahlen Welt nicht einverstanden ist:

>>> (1.0/103.0) * 103.0 
0.99999999999999989 

Oder vielleicht genauso seltsam, könnte man denken, dass für alle n, n + 1 != n. Im Floating-Point-Land, arbeiten nur Zahlen nicht so:

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

What every computer scientist should know about floating point numbers für eine ausgezeichnete Zusammenfassung der Probleme sehen.

Wenn Sie genaue Dezimaldarstellung benötigen, überprüfen Sie das Modul decimal, Teil der Python-Standardbibliothek seit 2.4. Sie können die Anzahl der signifikanten Zahlen angeben. Der Nachteil ist, dass es viel langsamer als Fließkomma ist, da Fließkommaoperationen in Hardware implementiert sind, während Dezimaldarstellungen rein in Software vorkommen. Es hat auch seine eigenen Ungenauigkeit Probleme, aber wenn Sie genaue Darstellung der Dezimalzahlen benötigen (z. B. für eine finanzielle Anwendung) ist es ideal.

Zum Beispiel:

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

>>> vom Dezimalimport * Traceback (innerste letzte): Datei "", Zeile 1, in? ImportError: Kein Modul namens Dezimal Es gibt einen Fehler, wenn ich versuche, Dezimal-Modul zu importieren, wo kann ich es bekommen? es klingt vielleicht dumm, aber ich bin neu bei Python. – user359925

+0

Dezimal ist ab Python Version 2.4 und höher verfügbar. –

+2

@zhack, wir sind eine Entwickler-Community, die Fragen ohne Gewinn beantwortet. Hör auf zu sagen, dass deine Fragen dumm sind. – Warty

0

Wie bereits erwähnt, geht es um Gleitpunkte eine Annäherung zu sein.

Wenn Sie Exaktheit möchten Sie eine Dezimalzahl verwenden können (was eine genaue Darstellung ist): 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

Beachten Sie, dass viele nicht-finanzielle Anwendungen keine Genauigkeit benötigen. Und Funktionen wie 'sin',' ln' und 'sqrt' geben in keiner Basis exakte Antworten zurück. – dan04

6

Es lohnt sich, zu beachten, dass Python 3.1 eine neue Floating-Point-Ausgaberoutine hat, dass diese in die Runde erwartete Weise (es wird auch auf Python 2.7 zurückportiert):

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] 

Vom What's New in Python 3.1 Dokument:

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

Wir können das Problem beheben durch diesen Befehl:

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

füge ich eine Antwort von @ Mark