Problema de redondeo con Python

Posible duplicado:
Error de redondeo de Python con números flotantes

Tengo un problema de redondeo en Python. Si calculo

32.50 * 0.19 = 6.1749999999999998

Pero esto debería ser 6.175. Si redondea 6.1749999999999998 con 2 decimales, muestra correctamente 6.18. Así que puedo vivir con eso.

Pero si calculo esto:

32.50 * 0.19 * 3 = 18.524999999999999

Esto debería ser 18.525. Si redondeo el valor 18.524999999999999 con dos decimales, se muestra 18.52.

Debería mostrarme 18.53. ¿Qué estoy haciendo mal y cómo puedo solucionarlo?

Si necesita aritmética exacta, podría usar el módulo decimal :

 import decimal D=decimal.Decimal x=D('32.50')*D('0.19') print(x) # 6.1750 print(x.quantize(D('0.01'),rounding=decimal.ROUND_UP)) # 6.18 y=D('32.50')*D('0.19')*D('3') print(y) # 18.5250 print(y.quantize(D('0.01'),rounding=decimal.ROUND_UP)) # 18.53 

Lo que todo científico informático debe saber sobre la aritmética de punto flotante .

En resumen, no debe confiar en valores precisos de números flotantes debido a la forma en que están almacenados en la memoria.

Consulte también la documentación de Python al respecto – Aritmética de punto flotante: problemas y limitaciones . Contiene el siguiente pasaje:

Por ejemplo, si intenta redondear el valor 2.675 a dos decimales, obtendrá este

>>> round(2.675, 2)
2.67

La documentación para la función round () incorporada dice que se redondea al valor más cercano, redondeando los lazos lejos de cero. Dado que la fracción decimal 2.675 está exactamente a la mitad entre 2.67 y 2.68, puede esperarse que el resultado aquí sea (una aproximación binaria) a 2.68. No lo es, porque cuando la cadena decimal 2.675 se convierte en un número binario de punto flotante, se reemplaza de nuevo con una aproximación binaria, cuyo valor exacto es

2.67499999999999989936431605997495353221893310546875

Como esta aproximación es ligeramente más cercana a 2,67 que a 2,68, se redondea hacia abajo.

Usa el módulo decimal de python para hacer aritmática flotante precisa

from decimal import Decimal, ROUND_UP

print (Decimal(32.50 * 0.19 * 3).quantize(Decimal('.01'), rounding=ROUND_UP))

Output: 18.53

No estás haciendo nada malo, y tampoco es culpa de Python . Algunos números decimales simplemente no se pueden representar con precisión como flotadores binarios.

Al igual que no puede escribir 1/3 en decimal ( 0.33333.... ), no puede escribir decimal 0.1 en binario ( 0.0001100110011001100110011001100110011001100110011... ).

Solución A:

Use print 32.5 * 0.19 – redondeará automáticamente el resultado.

Solución B:

Utilice el módulo Decimal si realmente necesita esta precisión, por ejemplo, al calcular con valores monetarios.

Solución C:

Utilice Python 3.2 o Python 2.7, que redondeará automáticamente el resultado en una sesión interactiva.

 Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> 32.50 * 0.19 6.175 

No creo que eso esté mal. Toma esto del intérprete de Python:

 >>> round(18.524999999999999,2) 18.52 >>> round(6.1749999999999998,2) 6.17 >>> 

En ambos casos, el número que se redondeaba era menos de 5, por lo que se redondeaba hacia abajo. 18.52, y 6.17.

Eso es correcto.

Una cosa que no entiendo es por qué obtienes 6.18, y yo obtengo 6.17. Estoy usando Python 3.2.2 (la última versión)

No estás haciendo nada malo. Esto se debe a la representación interna de los números:

Por ejemplo, prueba esto:

 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 

Si necesitas más precisión utiliza la representación decimal.