Какой класс использовать для представления денег?

Какой класс следует использовать для представления денег, чтобы избежать большинства ошибок округления?

Должен ли я использовать Decimal или простой встроенный number?

Есть ли какой-либо существующий класс Money с поддержкой конвертации валюты, который я мог бы использовать?

Есть ли подводные камни, которых мне следует избегать?


person Esteban Küber    schedule 10.09.2009    source источник
comment
Я всегда думал, что конвертация валюты — это просто умножение.   -  person SilentGhost    schedule 10.09.2009
comment
@SilentGhost: и да, и нет. Вы должны помнить, как вы собираетесь использовать имеющиеся у вас ценности. Как вы себя чувствуете, когда вы заплатили 2000 долларов США + 6300 аргентинских долларов + 1500 евро в прошлом году, а в этом году вы заплатили 4000 долларов США + 1200 аргентинских долларов + 500 евро? Есть много вещей, которые вы должны принять во внимание, поэтому объект Money должен будет сохранять историческое значение и текущее значение.   -  person Esteban Küber    schedule 10.09.2009
comment
Ловушка, которую следует избегать: использование чисел с плавающей запятой. См. Офисное пространство.   -  person    schedule 31.12.2011


Ответы (6)


Я предполагаю, что вы говорите о Python. http://code.google.com/p/python-money/ "Примитивы для работы с деньгами и валютами в Python" - название говорит само за себя :)

person juckobee    schedule 10.09.2009
comment
Глядя на code.google.com/p/ python-money/source/browse/trunk/money/ я вижу, что они используют Decimal для внутреннего представления :) - person Esteban Küber; 10.09.2009

Никогда не используйте число с плавающей запятой для представления денег. Плавающие числа не точно представляют числа в десятичной системе счисления. Вы закончите с кошмаром сложных ошибок округления и не сможете надежно конвертировать между валютами. См. краткое эссе Мартина Фаулера на эту тему.

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

Я не думаю, что python-money - хороший вариант, потому что он не поддерживался в течение достаточно долгого времени, и его исходный код имеет какой-то странный и бесполезный код, а обмен валюты просто сломан.

Попробуйте py-moneyed. Это улучшение по сравнению с python-money.

person Thiago Chaves    schedule 23.07.2012
comment
десятичное число основано на плавающей запятой, мне любопытно, как это решает проблему - person xenoterracide; 25.01.2020
comment
Как это исправляет или работает с проблемами с плавающей запятой, описано в первом разделе документации Python для десятичных чисел: docs.python.org/3/library/decimal.html Надеюсь, это поможет. - person NeverCast; 09.12.2020

Просто используйте decimal.

person S.Lott    schedule 11.09.2009
comment
decimal не подходит из-за того, как он обрабатывает точность. Предположим, вы обрабатываете суммы менее 10 миллиардов долларов с точностью до 0,01 доллара, поэтому вы сообщаете десятичной библиотеке, что ваши числа не будут длиннее 12 цифр. Теперь у вас две проблемы: ваш код не справляется с гиперинфляцией; и $0,01 будет отображаться как «0,010000000000». - person Pitarou; 04.06.2017

Возможно, вас заинтересует QuantLib для работы с финансами.

Он имеет встроенные классы для обработки типов валюты и требует 4 лет активной разработки.

person Jon W    schedule 10.09.2009
comment
Этот проект выглядит интересно, но может быть слишком много, я, скорее всего, для простоты буду использовать проект на чистом Python. - person Esteban Küber; 10.09.2009

Вы можете взглянуть на эту библиотеку: python-money. Поскольку у меня нет опыта работы с ним, я не могу комментировать его полезность.

«Трюк», который вы могли бы использовать для обработки валюты как целых чисел:

  • Умножьте на 100 / Разделите на 100 (например, $100,25 -> 10025), чтобы получить представление в «центах».
person ChristopheD    schedule 10.09.2009
comment
Многие системы учета отслеживают вещи гораздо точнее, чем до цента. - person Paul McMillan; 10.09.2009
comment
Верно, но все зависит от потребностей, я думаю... Библиотека quantlib, упомянутая в этой теме, кажется хорошим кандидатом на "серьезную" финансовую работу. - person ChristopheD; 10.09.2009

Простая, легкая, но расширяемая идея:

class Money():

    def __init__(self, value):
        # internally use Decimal or cents as long
        self._cents = long(0)
        # Now parse 'value' as needed e.g. locale-specific user-entered string, cents, Money, etc.
        # Decimal helps in conversion

    def as_my_app_specific_protocol(self):
        # some application-specific representation

    def __str__(self):
        # user-friendly form, locale specific if needed

    # rich comparison and basic arithmetics
    def __lt__(self, other):
        return self._cents < Money(other)._cents
    def __add__(self, other):
        return Money(self._cents + Money(other)._cents)

Вы можете:

  • Реализуйте в своем приложении только то, что вам нужно.
  • Расширяйте его по мере роста.
  • При необходимости измените внутреннее представление и реализацию.
person andruso    schedule 30.07.2013