2

I've been assigned to a code base responsible for millions of dollars of transactions, per quarter, and has been in use for over a decade. Sifting through the solution, I see doubles used everywhere to represent money and arithmetic is done on these variables; on the rare occasion is a decimal type used.

What is an apt approach to understand the extent of possible damage done by rounding errors due to using an inappropriate type for currency?

  • 3
    Oh boy, that's a broad task. There's no simple way to resolve that. – πάντα ῥεῖ Feb 14 at 19:09
  • 2
    Find a calculation where you think rounding is an issue. Plug in values and demonstrate what the issue is. Repeat this for a goodly sample of calculations to get an estimate of impact for the entire system. – BobDalgleish Feb 14 at 19:34
  • 1
    Doubles still have many significant digits. If the amounts are fairly small (IIRC up to ten decimal digits) you may be fine – recall that JavaScript even uses doubles to represent integer values! – amon Feb 14 at 19:38
  • 1
    unit and integration testing – Martin K Feb 14 at 21:21
3

You're right in being concerned about the use of floats for monetary amounts. Unless they are just used to calculate something which is then properly represented as a rounded scaled decimal (or an integral number of cents, which is equivalent,) they shouldn't be used to represent money.

However, the damage that could possibly be caused is very dependent on the exact use of these values, so you will indeed need to find out where these numbers are used in transactions and reports and where discrepancies in the sums can happen.

Unless round-off errors have been systematically siphoned off into some malevolent developer's private bank account (which happened in the past somewhere if I remember correctly) the direct monetary damage to the company or its customers is likely within reasonable limits, but you can't be certain before you've done your analysis. The effort needed to fix the problem may be several orders of magnitude higher than the damage, but may still be unavoidable.

  • Well, for indirect damage wait on the lawyers and IRS audits. Best plan to die before that fateful day. – Deduplicator yesterday
  • "...systematically siphoned off... which happened in the past somewhere if I remember correctly..." - wasn't it part of the plot of Superman III (1983), with Richard Pryor playing a computer programmer? – Steve yesterday
  • @Steve skeptics.stackexchange.com/questions/14925/… contains some pointers. Evidence for this actually having happened seem inconclusive. – Hans-Martin Mosner yesterday
3

Using single precision float for money is fatal. Float has only 24 bits of precision, so if you are using dollars, then anything above 2^18 dollars has a resolution worse than one cent. So anything above $263,000 or so has big problems.

Using double precision is much much less of a problem. If you have an amount of one trillion dollars in double precision, the lowest bit in that number has a value of 2^-14 dollar, that is about 1/164th of a cent. Rounding error for numbers in that range is half that. For an amount of a billion dollars, errors are 1,000 times smaller.

If you need to look at rounding errors, they will be negligible. If you have calculations that must be done according to specific rules, and must end up in the exact right amount, and there are (costly) legal consequences, there might be problems.

If results have been rounded, say to cents, examine carefully how that rounding has been done. It could be biased which could have produced systematic errors.

  • When it comes to systematic error, the question is in whose favour is the error! – Steve yesterday
1

Floating point numbers are simply not suitable for storing exact but arbitrary numeric values; every floating point number is just an approximation of a numeric value. Sure, some numbers can be represented exactly as a floating point value but many cannot and then you will have an error that can vary a lot, so it's better to always treat them as an approximation. E.g. even a simple value as 0.2 cannot be exactly represented as a double value. Calculating 0.2 + 0.1 in C# (assuming both are double values) results in 0.30000000000000004, whereas 0.3 would have been correct.

Money can actually easily be represented as integers, just store it as cent values. A 64 bit integer value is more than suitable for this task. During calculations you can convert it to higher precision values first (like decimals), perform the operation, and finally convert it back to cent at the end, using appropriate rounding but for many tasks you don't have to (addition, subtraction, and multiplication will be fine with integer values).

The problem with determining the error is that errors sum up. If you calculate interests, the error will be too small to be significant but if you calculate compound interests of a huge amount of money and then use the result in other calculations, the error can become significant. So if you just look what the error of a single operation is, then this may not be useful as this operation may be used as one operation in a set of operations to calculate a single result in the end.

Also errors can sum up over the years. If you store an account balance as a double and always round the value to two digits after the period for displaying but internally keep the full precession, you may get correct results for years and after 30 years all of a sudden you will be off by one cent which does not only depend on the balance of the account but also on the number of transactions over the years. Sure, most people will think "One cent, is nowhere near significant". Well, if you are a finance institute and you have 100 million accounts and each is off by just one cent, your total balance is off by 1 million dollar and I would call that significant.

I'm not sure of what exactly your code is calculating and how often a day it is doing so without interim rounding, so I cannot really provide a better answer here. E.g. if the money is really just transferred (subtracted from account A and added to account B), using double will not easily cause significant issues. You usually need more complex operations that include multiplications, exponentiations/square roots to quickly accumulate significant errors.

New contributor
Mecki is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • 2
    "simply not suitable for storing exact but arbitrary numeric values" - nor can any other number system. The problem with IEEE floats isn't that they aren't exact, it's that their rounding behaviors are different than most people are used to. – whatsisname yesterday
  • What @whatsisname says: How much is one third of a dollar in decimal? – gnasher729 yesterday
-3

To my gut feeling, double precision should be quite good for most practical cases. I don't risk to evaluate any numbers at the moment, but I think there is very good chance the errors would be negligible small for any decision making.

What can be an issue is that there may be a few cents (or whatever your currency units) in an audited results, like accounting. Then even small errors may get the company into troubles.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.