views:

352

answers:

7

What is your advice on:

  1. compensation of accumulated error in bulk math operations on collections of Money objects. How is this implemented in your production code for your locale?
  2. theory behind rounding in accountancy.
  3. any literature on topic.

I currently read Fowler. He mentions Money type, it's typcal structure (int, long, BigDecimal), but says nothing on strategies.

Older posts on money-rounding (here, and here) do not provide a details and formality I need.

Thoughts I found in the inet relate to "Round half even" as the best way to balance error.

Thanks for help.

+2  A: 

Use Banker's rounding. You round to the nearest two-penny.

http://www.xbeat.net/vbspeed/i_BankersRounding.htm

You can expand upon this to round toward the nearest two-penny instead. So 22.5 rounds to 22, but 23.5 rounds to 24. 23.1 and 22.9 both round to 23. However, the original banker's algorithm is more popular.

glowcoder
@glowcoder: Thanks for expansion.
Max
+1  A: 

According to trusted industry publications* that I have studied extensively, one best practice works as follows:

  1. Round down.
  2. Transfer remainder into private checking account.

* references: Superman III, Office Space

Brian MacKay
hehe. appreciate this :)
Max
and remember to put the decimal at the right place :)
Anurag
+2  A: 

Never store money values in a double or float - use an int or long as there is no way to store 0.1 accurately in binary.

Robert
Max
@max: what is this, accountancy overflow? ;)
Robert
What operations are you doing? Standard arithmetic ops won't have any rounding errors - that's the purpose of using a fixed-point representation.
Nick Johnson
+2  A: 

It all depends on the application. Hopefully there aren't too many situations where rounding is required. For example, transferring money from one account to another requires no rounding.

For situations where rounding is required, it doesn't really matter what you do as long as you pick a policy, communicate it, and stick to it. For instance, I believe the interest on my savings account rounds down to the nearest penny.

Keith Randall
+1  A: 

I've worked a bit (just a bit) with monetary amounts and I was extremely curious as to the strategy used in my company...

It turns out that we use double, but they've thought about it.

The thing is that the amounts we deal with are not that great (say less than 10k) and at most we need 3 digits after the decimal, for a total of 7 significant digits.

Since we are using 64bits software (and C++) the double type offers enough significant digits for the number of operations we carry on it :)

If you need more precision, there are algorithms to use (for example while adding multiple moneys) but personally I think the heart of the issue comes more from:

  • conversion from one money to another, which keeps changing of course
  • printing issues, with some moneys requiring no decimal, others requiring 2 at most, etc...

Perhaps could you expand on the operations you're doing ?

Matthieu M.
Hi, Matthieu. I've also seen one legacy system working on doubles...We face several problems (your mentioned money conversion as well). Others are akin to mentioned at www.ciceuta.es/euro/doc/1/eup22en.pdf . Typical is to have a discrepancy in total sum of small numbers obtained by divisions and multiplications.Seems, I shall increase the precision for those intermediate ops and possibly rebuild calculations (however part of that "small numbers" data is not controlled by me). I come to the conclusion that either we ignore the error, or compensate by balancing rounging like Round-half-even.
Max
+1  A: 

There are many rounding issues when recording financial data. First issue is ability to store and retrieve exact decimal numbers

  • most databases offer decimal data type on which you can specify the number of digits before and after decimal point (currencies vary in number of decimal digits, too, I've dealt with currencies with 0, 2, 3 decimal digits)
  • when dealing with this data and you want to avoid any unexpected rounding errors on the application side you can use BCD as generic approach, or you can use integers to represent any fixed decimal notation or mix your own

If this first issue is sorted out then no addition (or substraction) can introduce any rounding errors. Same goes for multiplication by integer.

The second issue, after you are able to store and retrieve data without loss of information, are expected rounding errors due to division (or multiplication by non integer).

For example if your currency format allows 2 decimals and you want to store transaction that records balances a debit of 10 to 3 equal pieces you can only store it like

10.00  
-3.33  
-3.33  
-3.33  

and

-0.01 

(rounding error)

This is expected problem that will occur regardless of the data type storage choice and that needs to be taken care of if you want your accounts to balance. This situation is mainly introduced by division (or by multiplication by non integers that have many significant digits).

One way to deal with this is to verify if your data balances after such operations and recognize the allowed rounding difference as opposed to an error situation.

EDIT: As for references to literature, this one seems interesting and not too long and concerns quite wide audience with interesting scenarios.

Unreason
@Unreason: Thanks for reminding me BCD stuff. Yeah, I'm sure persistance is ok and permits exact decimals. Generally my problem can be distilled to your point about summing up small rouded amounts. Pity is that I'm not fully controlling this break-down I sum up by myself :). So I possibly have to resort to Round half even Gaussian method or any other statistical...
Max
@Max, well the strategy on dealing with these accumulated rounding errors depends on your business rules (sometimes you are required to make amounts equal and you have to record the error, other times it is allowed to distribute the rounding errors).
Unreason
@Unreason: Talked to BA, we shall make changes to our part and also ask for changes in external system that feeds us this those "small unprecise" break-down amounts. Anyway this SO post was valuable - at least I started to feel that rounding staff is more entertaining than I could ever expected :)
Max
A: 

What you should do may well be informed by the conventions of the market or jurisdiction you are operating in. For example, pricing bonds in the Australian market requires that you round certain intermediate operations to 8 decimal places. The final price is quoted to a specific number of decimals (3 I think off the top of my head).

If you are dealing with an accounting app, I would expect the relevant accounting standards for your legal environment to possibly dictate this.

James Webster