Referencia: Limite los flotantes a dos decimales {DH}
TLDR;)
Solucionado el problema de redondeo de entrada/salida finalmente resuelto por Python 2.7.0 Y 3.1.
Un número redondeado correctamente se puede convertir de ida y vuelta inversamente:str -> float() -> repr() -> float() ...
o Decimal -> float -> str -> Decimal
El tipo decimal ya no es necesario para el almacenamiento.
(Por supuesto, puede ser necesario redondear un resultado de sumar o restar números redondeados para eliminar los errores acumulados del último bit. La aritmética decimal explícita puede ser útil, pero una conversión a cadena a través de str()
(es decir, redondear a 12 dígitos válidos) suele ser lo suficientemente bueno a menos que se requiera una precisión extrema o un número extremo de operaciones aritméticas consecutivas).
examen infinito:
import random
from decimal import Decimal
for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-)
assert float(repr(x)) == x # Reversible repr() conversion.
assert float(Decimal(repr(x))) == x
assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round.
if x >= 0.1: # Implicit rounding to 12 significant digits
assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors.
y = 1000 * x # Decimal type is excessive for shopping
assert str(y) == repr(round(y, 12 - 3)) # in a supermaket with Python 2.7+ :-)
documentación
Consulte las Notas de la versión de Python 2.7 – Otros cambios en el idioma en el cuarto párrafo:
conversiones entre números de punto flotante y cadenas ahora son correctamente redondeado en la mayoría de las plataformas. Estas conversiones ocurren en muchos lugares diferentes: str() para números flotantes y complejos; constructores flotantes y complejos; formato numérico; Serialice y deserialice números de coma flotante y números complejos con el
marshal
,pickle
Yjson
módulos; Analizar flotantes y literales imaginarios en código Python; y conversión de decimal a flotante.Relacionado con esto está el desempeñar() un número de punto flotante x ahora devuelve un resultado basado en el cadena decimal más corta garantizada para ser redondeada a x con redondeo correcto (con modo de redondeo de semicircular a recto). Anteriormente, devolvía una cadena basada en el redondeo de x a 17 decimales.
El problema relacionado
Más información: el formato de float
antes de Python 2.7 era similar al actual numpy.float64
. Ambos tipos utilizan la misma precisión doble IEEE-754 de 64 bits con mantisa de 52 bits. esa es una gran diferencia np.float64.__repr__
a menudo se formatea con un decimal excesivo para no perder bits, pero no hay un número IEEE 754 válido entre 13.949999999999999 y 13.950000000000001. El resultado no es agradable y la conversión repr(float(number_as_string))
no es reversible con numpy. Por otra parte: float.__repr__
está formateado para que cada dígito importe; la secuencia no tiene espacios y la conversión es reversible. Simple: si tiene un número numpy.float64, conviértalo en un número flotante regular para que esté formateado para humanos, no para procesadores de números; de lo contrario, no se necesita nada más con Python 2.7+.