What's the right way to handle monetary values in code?
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?)
8 comments
[ 3.1 ms ] story [ 25.0 ms ] threadRound down:
discount = 33 value / 100;
Round up:
discount = (33 value + 99) / 100;
Round to nearest:
discount = (33 value + 50) / 100;
In banking, I believe the convention is to round to the nearest penny, and round half-pennies to the nearest even penny.
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 :)