What class to use for money representation?
Asked Answered
S

6

51

What class should I use for representation of money to avoid most rounding errors?

Should I use Decimal, or a simple built-in number?

Is there any existing Money class with support for currency conversion that I could use?

Any pitfalls that I should avoid?

Sixtyfour answered 10/9, 2009 at 17:52 Comment(3)
I always thought that currency conversion is just multiplication.Selfpossession
@SilentGhost: Yes and no. You have to keep in mind how are you going to use the values that you have. How do you do when you payed U$S2000 + AR$6300 + €1500 last year and this year you payed U$S4000 + AR$1200 + €500? There are many things that you have to take into account, so a Money object would need to save the historical value and current value.Radiomicrometer
Pitfall to avoid: using floating point numbers. See Office Space.Carbohydrate
A
10

http://code.google.com/p/python-money/ "Primitives for working with money and currencies in Python" - the title is self explanatory :)

Auscultation answered 10/9, 2009 at 18:1 Comment(1)
Looking at code.google.com/p/python-money/source/browse/trunk/money/… I can see that they do use Decimal for internal representation :)Radiomicrometer
A
42

Never use a floating point number to represent money. Floating numbers do not represent numbers in decimal notation accurately. You would end with a nightmare of compound rounding errors, and unable to reliably convert between currencies. See Martin Fowler's short essay on the subject.

If you decide to write your own class, I recommend basing it on the decimal data type.

I don't think python-money is a good option, because it wasn't maintained for quite some time and its source code has some strange and useless code, and exchanging currencies is simply broken.

Try py-moneyed. It's an improvement over python-money.

Arlyn answered 23/7, 2012 at 21:25 Comment(3)
decimal is based on a floating point, I'm curious how it fixes the problemDonnenfeld
How it fixes or works around floating point problems is described in the first section of the Python docs for decimal: docs.python.org/3/library/decimal.html Hope that helps.Anetta
@Donnenfeld I think you are confusing "floating point model" with IEEE 754 floating point. The principle of a floating point model isn't broken, but using hardware based IEEE 754 (binary floating point) for decimal currency calculation is broken.Micrometeorology
T
21

Just use decimal.

Thomasinethomason answered 11/9, 2009 at 2:20 Comment(2)
decimal isn’t suitable because of the way it handles precision. Suppose you’re handling amounts less than $10 bn with a precision of $0.01, so you tell the decimal library your numbers will be no more than 12 digits long. Now you have two problems: your code can’t handle hyper-inflation; and $0.01 will be displayed as '0.010000000000'.Saldana
@Saldana Forgive my ignorance, but why would you ever reduce the precision, especially in an app that might encounter hyper-inflation? And how do you get that output for $0.01? I tried decimal.getcontext().prec = 12; print(decimal.Decimal('0.01')) but it prints 0.01 with no trailing zeros. Even if you did get that output, why wouldn't you round it before display?Hayman
A
10

http://code.google.com/p/python-money/ "Primitives for working with money and currencies in Python" - the title is self explanatory :)

Auscultation answered 10/9, 2009 at 18:1 Comment(1)
Looking at code.google.com/p/python-money/source/browse/trunk/money/… I can see that they do use Decimal for internal representation :)Radiomicrometer
L
6

You could have a look at this library: python-money. Since I've no experience with it I cannot comment on its usefullness.

A 'trick' you could employ to handle currency as integers:

  • Multiply by 100 / Divide by 100 (e.g. $100,25 -> 10025) to have a representation in 'cents'
Laurinelaurita answered 10/9, 2009 at 17:59 Comment(2)
Many accounting systems track things far more precisely than to the cent.Conveyor
True, but all depends on the needs I guess... The quantlib library referenced in this thread seems a good candidate for 'serious' financial work.Laurinelaurita
K
5

You might be interested in QuantLib for working with finance.

It has built in classes for handling currency types and claims 4 years of active development.

Kealey answered 10/9, 2009 at 17:55 Comment(1)
This project looks interesting, but may be a bit too much, I will most likely use a pure python project for simplicity.Radiomicrometer
E
5

Simple, light-weight, yet extensible idea:

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)

You can:

  • Implement only what you need in your application.
  • Extend it as you grow.
  • Change internal representation and implementation as needed.
Exhilarant answered 30/7, 2013 at 7:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.