десятичное сравнение python

десятичное сравнение python

>>> from decimal import Decimal >>> Decimal('1.0') > 2.0 True 

Я ожидал, что он правильно преобразует 2.0, но после прочтения через PEP 327 я понимаю, что есть некоторая причина для непрактичного преобразования float в Decimal, но в этом случае он не должен поднимать TypeError, как в этом случае

 >>> Decimal('1.0') + 2.0 Traceback (most recent call last): File "<string>", line 1, in <string> TypeError: unsupported operand type(s) for +: 'Decimal' and 'float' 

так и весь другой оператор / -% // и т. д.

поэтому мои вопросы

  1. это правильное поведение? (не поднимать исключение в cmp)
  2. Что делать, если я получаю свой собственный класс и правильно конвертер float в основном Decimal (repr (float_value)), есть ли какие-либо оговорки? мой вариант использования касается только сравнения цен

Сведения о системе: Python 2.5.2 на Ubuntu 8.04.1

3 Solutions collect form web for “десятичное сравнение python”

Re 1, это действительно то поведение, которое мы разработали – правильно или неправильно, поскольку это может быть (извините, если это касается вашего использования, но мы пытались быть генералом!).

В частности, долгое время каждый объект Python мог быть подвержен неравенству по сравнению с любым другим – объекты типов, которые на самом деле не сравнимы, сравниваются произвольно (последовательно в данном пробеге, а не во всех прогонах); основной вариант использования – сортировка гетерогенного списка для группировки элементов в нем по типу.

Исключение было введено только для комплексных чисел, что делало их несопоставимыми ни с чем, но это было еще много лет назад, когда мы иногда были кавалерами о нарушении совершенно хорошего кода пользователя. В настоящее время мы гораздо более жестко поддерживаем обратную совместимость в основном выпуске (например, вдоль линии 2.* и отдельно по 3.* , хотя несовместимость разрешена между 2 и 3 – действительно, это все, что нужно иметь 3.* серия, позволяющая фиксировать прошлые дизайнерские решения даже несовместимыми способами).

Произвольные сравнения оказались более трудными, чем их ценность, что привело к путанице пользователей; и группировка по типу теперь может быть легко получена, например, с аргументом key=lambda x: str(type(x)) для sort ; поэтому в сопоставлениях Python 3 между объектами разных типов, если только сами объекты специально не позволяют это в методах сравнения, вызывает исключение:

 >>> decimal.Decimal('2.0') > 1.2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: Decimal() > float() 

Другими словами, в Python 3 это ведет себя так, как вы думаете. но в Python 2 он не (и никогда не будет в любом Python 2.* ).

Re 2, вы будете в порядке – хотя, посмотрите на gmpy, поскольку я надеюсь, что это интересный способ конвертировать двойники в бесконечные прецизионные дроби через деревья Farey. Если цены, с которыми вы имеете дело, точны не более, чем центы, используйте '%.2f' % x а не repr(x) ! -)

Вместо подкласса Decimal я использовал бы заводскую функцию, такую ​​как

 def to_decimal(float_price): return decimal.Decimal('%.2f' % float_price) 

так как после его создания результирующий десятичный знак является совершенно обычным.

Это больше, чем сравнение, потому что по умолчанию оно работает для всех объектов.

 >>> 'abc' > 123 True 

Decimal справедливо только потому, что оно правильно следует спецификации. Является ли спецификация правильным подходом, это отдельный вопрос. 🙂

Только обычные оговорки при работе с поплавками, которые кратко суммируются: остерегайтесь случаев кросс, таких как отрицательный ноль, +/- бесконечность и NaN, не проверяйте равенство (относящееся к следующей точке) и рассчитывайте на математику немного неточно.

 >>> print (1.1 + 2.2 == 3.3) False 

Если это «правильно», это вопрос мнения, но обоснование того, почему автоматическое преобразование отсутствует в ППК, и это было принято. Предостережение в основном состоит в том, что вы не всегда можете точно конвертировать между float и decimal. Поэтому преобразование не должно быть неявным. Если вы в своем приложении знаете, что у вас никогда не будет достаточно значительных чисел, чтобы это повлияло на вас, создание классов, которые допускают это неявное поведение, не должно быть проблемой.

Кроме того, одним из основных аргументов является то, что случаев использования в реальном мире не существует. Скорее всего, это будет проще, если вы просто используете Decimal везде.

Python - лучший язык программирования в мире.