Hacker News new | ask | show | jobs
by racingmars 1482 days ago
Financial calculations need to be done with fixed-point, not floating-point, arithmetic. Floating-point can't store the exact value of most fractional numbers, and especially over many transactions for many customers the floating-point errors will accumulate.

You need basic addition and subtraction to always be exact (e.g. $15.27 + $91.31 needs to come out as $106.58, not $106.5799999999999999999998), and for operations that may have remainders beyond your desired number of digit precision, you need deterministic rounding or other rules to handle it.

If you're ever writing any code that handles money, DO NOT use just naively use float and double types in your code!

4 comments

Why would you ever want monetary amounts as fractions or any kind? Why would you want to separate dollars from cents? Just represent them in cents or other smallest units ($15.27 would be 1527), and only make the distinction between dollars and cents for human-readable output. Problem solved. I don't understand what BCD would solve here vs plain binary integers.
> Why would you ever want monetary amounts as fractions or any kind?

If you can exchange arbitrary currency (and other commodity) in specified whole units with no other restrictions, then if you need to track prices, the prices need to be tracked as arbitrary rational numbers.

BCD is, of course, inadequate for that, but it's the most general reason for why monetary amounts may need fractions, IMO.

BCD does mean that when the requirements change from “we need to track to the cent” to “we need to track to the mil”, you change one constant as to the minimum allowed precision, and no other code or existing data. Whereas “use integer multiples of the minimum unit” makes that messier. Also, if you have different minimum units in different parts of an enterprise, using BCD makes sharing between them easier.

When currencies are represented as integers you have trouble doing transactions in multiple currencies.

Floating point is out of the question, so division, multiplication, etc was more accurate in BCD than in integers when different currencies were involved.

as soon as interest or taxes are involved, you'll end up with fractions of cents. Or if you want to split an uneven amount between people.
Actually it's worse than that; they're talking about decimal floating point, which appears to work in obvious tests - $15.270 + $91.310 is $106.58. But (assuming 5 mantissa digits for example, but it works with any number), you can do the following:

  balance   91.31 [+291310]
         +1000.00 [+410000] temporary credit
  balance 1091.30 [+410913] ULP lost
         -1000.00 [-410000] temporary credit deducted
  balance   91.30 [+291300] successfully stole 1 cent
  repeat on each account/transaction/etc
Real examples are obviously less blatant than this, but you get the idea.

Decimal floating point should never be supported for anything in any capacity, and use of any floating point in financial software should be considered material proof of either gross incompentence or negligence, or intent to commit fraud.

“Financial functions for calculating the time value of money, depreciation etc” isn’t “handling money” and is perfectly fine to do in floating point. Essentially everyone out there does it in Excel or Python.
Can you recommend some good comprehensive books on fixed-point, big num Maths with code examples in C/C++ ? If it has practical applications showing usage that would be even better. I am interested in knowing how you get precision in Computers both by using floating-point and by substituting it with equivalent fixed-point representations.