Why not FP for Money?

Christos TZOTZIOY Georgiou tzot at sil-tec.gr
Wed Sep 22 10:41:45 EDT 2004


On 21 Sep 2004 00:25:25 -0700, rumours say that Barkmann at gmail.com
(Chris Barker) might have written:

>Hi all,
>
<snip: this is not a troll, ok>
>
>I've seen it suggested various times that one should use fixed point
>for money, perhaps micro cents represented as integers. However, if
>you do that, you need to make sure you do all the rounding correctly.
>If you were to use FP, you could have your IEEE 754 hardware do the
>rounding for you, and get better performance to boot. If you are
>rounding to cents at the end anyway, I can't see that the errors you'd
>get with 64 bit FP numbers would ever be an issue.

See simple example at end.

>I understand that when your numbers got large enough, you'd start to
>lose the pennies, but how many of us have the luxury of doing
>computation with quadrillions of dollars actually care about the
>pennies? Besides, you could check for HUGE numbers and do something
>special with them if you wanted.

If you lose pennies, you better hope auditors don't read this newsgroup.

>What am I missing here?

The following function imitates real life: sending quotes for a part to
a customer.  We order in USD from SGI, we sell in EUR.  An Excel sheet
(written by someone in the QA dept!) does the dirty job (and thankfully,
when I noticed the inconsistency, I corrected things, even if these
quotes won't ever be audited... but I felt embarassed nonetheless):

def quote(tp):
    def _calc_vat(amount):
        amount= tp(repr(amount))
        vat= amount * tp('0.18')
        total= amount + vat
        return amount, vat, total
    eur_to_usd_rate= 1.184 # the actual rate used April 22, 2004
    amount_usd, vat_usd, total_usd= _calc_vat(2025)
    amount_eur, vat_eur, total_eur= _calc_vat(2025/eur_to_usd_rate)
    gfmt= "%-6.6s: USD %10.2f EUR %10.2f"
    print gfmt % ("Amount", amount_usd, amount_eur)
    print gfmt % ("Vat", vat_usd, vat_eur)
    print gfmt % ("Total", total_usd, total_eur)

import decimal
quote(decimal.Decimal)
quote(float)

Run it with Python 2.4.  See what goes wrong?  Put the numbers in an
Excel sheet too.

Of course, one can take extra precautions to always have correct numbers
when working with floats and monetary amounts (eg. I did that for the
Excel sheet the sales dpt used).  Why bother, though, if one has the
Decimal type?
-- 
TZOTZIOY, I speak England very best,
"Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek



More information about the Python-list mailing list