У меня есть большой объем кода на Python, который пытается обрабатывать числа с точностью до 4 знаков после запятой, и я застрял на Python 2.4 по многим причинам. Код очень упрощен math (это код управления кредитами, который в основном берет или добавляет кредиты)
В нем смешано использование float и Decimal (MySQLdb возвращает объекты Decimal для типов SQL DECIMAL).После нескольких странных ошибок, возникающих при использовании, я обнаружил, что основная причина всего заключается в том, что несколько мест в коде сравниваются с плавающими и десятичными знаками.
Я дошел до таких случаев:
>>> from decimal import Decimal
>>> max(Decimal('0.06'), 0.6)
Decimal("0.06")
Теперь я опасаюсь, что я не смогу уловить все такие случаи в коде. (нормальный программист будет продолжать делать x> 0 вместо x> Decimal ('0.0000'), и этого очень трудно избежать)
Я придумал патч (вдохновленный улучшениями пакета decimal в 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
Я просто делаю это в библиотеке с очень ранней загрузкой, и это изменит поведение пакета decimal, разрешив преобразование float в Decimal перед сравнением (чтобы избежать попадания объекта python по умолчанию для сравнения объектов).
Я специально использовал str вместо repr, поскольку он исправляет некоторые случаи округления чисел с плавающей запятой. Например.
>>> Decimal(str(0.6))
Decimal("0.6")
>>> Decimal(repr(0.6))
Decimal("0.59999999999999998")
Теперь мой вопрос: Я что-то здесь упускаю? Это достаточно безопасно? или я здесь что-то ломаю? (я думаю, у авторов пакета были очень веские причины так сильно избегать поплавков)