

What's the right way to handle monetary values in code? - count

I've seen a number of things saying to use integers of the smallest value (say, cents for USD) to avoid floating point rounding issues.
How does that work when you have to do math on them - is it proper to just 'eat' or eliminate the remainders (say, a 33% discount on $1.00USD is how much off?  How much off is a 33% discount on $.99?)
======
cperciva
In Tarsnap I use a pair of 64-bit values, one for dollars and one for
attodollars. I figure I don't mind losing a few attodollars to rounding, and
I'm unlikely to ever have revenue exceeding 2^64 dollars.

------
vshlos
What you need is a fixed point decimal. I found this article asking the same
question. [http://stackoverflow.com/questions/1019939/ruby-on-rails-
bes...](http://stackoverflow.com/questions/1019939/ruby-on-rails-best-method-
of-handling-currency-money) Fixed point is what is supposed to be used for
money. Databases currently have a "Money" type.

~~~
malux85
Yep this is the right way to go .. use the Money type when you can.

Just remember though, don't hard code 2 decimal places through your system. I
have had to write financial software that's needed to be flexible enough to be
accurate to 4 decimal places. Some clients can have strict requirements on
financial software, make sure you ask all the right questions first:

\- Do you have dollar discounts, or percentage discounts, or both?

\- When you calculate tax, you should do it on a per-line basis (don't sum up
the invoice and calculate tax on the end - some countries / states / whatever
can have tax exempt items)

\- When you calculate discount, calculate dollar value to N decimal places,
then round to Y decimal places, then calculate tax on the rounded figure

All of this might seem like a nightmare for a few cents, but it really matters
if you're dealing with many items (where small differences add up over many
items) or you have to integrate with another third party system, and you might
need to make sure your totals match theirs exactly (to the cent)

EDIT: Citing my sources ... I have worked on financial software that spans New
Zealand, Australia and Global stuff too. I have had to integrate with (and
learn intimately) 40+ accounting packages. All of them behave slightly
differently in terms of rounding, but your best best is to -

\- Match the system you're integrating with

\- If you must 'lose' a cent, favour the customer (as the above comment says)

Godspeed :)

------
andyv
Assuming truncating division:

Round down:

discount = 33 value / 100;

Round up:

discount = (33 value + 99) / 100;

Round to nearest:

discount = (33 value + 50) / 100;

~~~
count
But which method is _appropriate_ for financial code?

~~~
abeld
I would use whichever errs in favor of the customer. Its only one cent, after
all.

