Tengo una gran cantidad de código python que intenta manejar números con 4 precisión decimal y estoy atrapado con python 2.4 por muchas razones. El código hace matemáticas muy simplistas (es un código de administración de crédito que toma o agrega créditos en su mayoría)Mal en el decimal/flotante python
Tiene uso entremezclado de float y Decimal (MySQLdb devuelve objetos decimales para tipos SQL DECIMAL). Después de varios errores extraños que surgen del uso, he encontrado que la causa raíz de todos son unos pocos lugares en el código que flotan y se están comparando los decimales.
llegué a casos como éste:
>>> from decimal import Decimal
>>> max(Decimal('0.06'), 0.6)
Decimal("0.06")
Ahora mi miedo es que yo no podría ser capaz de atrapar todos los casos en el código. (un programador normal seguirá haciendo x> 0 en lugar de x> Decimal ('0.0000') y es muy difícil de evitar)
He creado un parche (inspirado en las mejoras del paquete decimal en Python 2.7) .
import decimal
def _convert_other(other):
"""Convert other to Decimal.
Verifies that it's ok to use in an implicit construction.
"""
if isinstance(other, Decimal):
return other
if isinstance(other, (int, long)):
return Decimal(other)
# Our small patch begins
if isinstance(other, float):
return Decimal(str(other))
# Our small patch ends
return NotImplemented
decimal._convert_other = _convert_other
yo sólo lo hacen en una biblioteca de carga muy temprano y que va a cambiar el comportamiento del paquete decimal al permitir la flotación a la conversión decimal antes de comparaciones (para evitar golpear objeto por defecto de Python para oponerse comparación).
Utilicé específicamente "str" en lugar de "repr", ya que corrige algunas de las cajas de redondeo del flotador. P.ej.
>>> Decimal(str(0.6))
Decimal("0.6")
>>> Decimal(repr(0.6))
Decimal("0.59999999999999998")
Ahora mi pregunta es: Me estoy perdiendo algo aquí? ¿Es esto bastante seguro? o estoy rompiendo algo aquí? (Estoy pensando que los autores del paquete tenían razones muy importantes para evitar flotadores tanto)
Solo una nota que el "return NotImplemented" es del propio paquete decimal.py. Las dos líneas que he agregado están entre los comentarios. Estoy de acuerdo con su enfoque, sin embargo, en esta implementación, Python permite comparaciones lógicamente insanas entre los objetos que asumimos que son ambos números. Hmm, otra idea podría ser generar un error en lugar de una conversión implícita, pero independientemente, creo que tengo que hacer algo ... –
'return NotImplemented' es correcto y es el correcto, [documentación especificada] (http: // docs .python.org/reference/datamodel.html # emulating-numeric-types) a devolver para una comparación no admitida. Permite a Python intentar encontrar otra forma de hacer las cosas. – aaronasterling
+1 por usar el término "parche de mono", que me llevó al término wikipedia, para encontrar que proviene de "parche de guerrilla", como en guerrilla =). – Tommy