2010-06-06 13 views
10

Soy un poco confundido por qué pitón añaden un número decimal adicional en este caso flotante, por favor ayuda a explicarpitón número

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

1 para hacer una pregunta inteligente, no suponiendo que se trataba de un error en Python. –

+1

Similar a http://stackoverflow.com/questions/2880547/python-rounding-problem –

+2

posible duplicado de [¿Por qué los números decimales no se representan exactamente en binario?] (Http: // stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represents-exactly-in-binary) –

Respuesta

13

números de punto flotante son una aproximación, que no pueden almacenar números decimales con exactitud. Debido a que intentan representar un rango muy grande de números en solo 64 bits, deben aproximarse en cierta medida.

Es muy importante tenerlo en cuenta, ya que da lugar a algunos efectos secundarios extraños. Por ejemplo, es muy razonable pensar que la suma de diez lotes de 0.1 sería 1.0. Si bien esto parece lógico, también está mal cuando se trata de coma flotante:

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

Se podría pensar que n/m * m == n. Una vez más, de punto flotante mundo está de acuerdo:

>>> (1.0/103.0) * 103.0 
0.99999999999999989 

O quizás tan extraña, uno podría pensar que para todos n, n + 1 != n. En el punto de la tierra flotante, números simplemente no funcionan así:

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

Ver What every computer scientist should know about floating point numbers para un excelente resumen de los temas.

Si necesita representación decimal exacta, consulte el módulo decimal, parte de la biblioteca estándar de python desde 2.4. Le permite especificar el número de cifras significativas. La desventaja es que es mucho más lento que el punto flotante, porque las operaciones de punto flotante se implementan en el hardware, mientras que las operaciones decimales ocurren puramente en el software. También tiene sus propios problemas de imprecisión, pero si necesita una representación exacta de los números decimales (por ejemplo, para una aplicación financiera) es ideal.

Por ejemplo:

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

>>> a partir de la importación decimal * Traceback (el último más interno): Archivo "", línea 1, in? ImportError: Ningún módulo llamado decimal hay un error cuando intento importar el módulo decimal, ¿dónde puedo obtenerlo? Puede sonar estúpido, pero soy nuevo en Python. – user359925

+0

decimal está disponible desde Python versión 2.4 y posterior. –

+2

@zhack, somos una comunidad de desarrolladores que responde preguntas sin obtener ganancias. Deja de decir que tus preguntas son estúpidas. – Warty

0

Como se mencionó antes, es todo acerca de puntos flotantes son una aproximación.

Si desea exactitud se puede utilizar un decimal (que es una representación precisa): 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

Tenga en cuenta que muchas aplicaciones no financieras NO NECESITAN la exactitud. Y funciones como 'sin',' ln' y 'sqrt' no devuelven respuestas exactas en ninguna base. – dan04

6

Vale la pena tener en cuenta que Python 3.1 tiene una nueva rutina de salida de coma flotante que completa esta en el forma esperada (que también ha sido portado a 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] 

Desde el What's New in Python 3.1 documento:

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

Podemos solucionarlo por este comando:

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

añado una respuesta de @ Marcos