12

I was reading this question and the accepted answer says that BigDecimal is the best type for representing currency values. I've also seen several other questions support the use of big decimal.

Why is BigDecimal the best type? I don't understand the relevance of arguments such as precise calculations or people with large net worth. I am pretty sure that there are no currencies that round to the 10th decimal place, and almost no one has 8-bytes worth of money (if it were to store it as a long).

For taxes and other intermediary calculations, I can see how it is important to make sure you are using a proper type that doesn't round/truncate values prematurely, but that doesn't seem relevant to me either since an error of 0.0000000001 cents on the dollar does not seem that big to me.

It may be due to my lack of understanding of the importance of accuracy when it comes to financial statements, so perhaps someone can also clarify whether a millionth of a cent is significant as a final number.

11
  • 4
    In my opinion the best data structure for storage is a integral type set to the lowest denomination you care about: i.e. think in cents or decicents ($0.001) instead of dollars. Feb 11, 2014 at 16:54
  • 1
    @MxyL absolutely. I've written a class that does exactly that. You may be interested in reading Solutions for floating point rounding errors
    – user40980
    Feb 11, 2014 at 16:57
  • 1
    @MichaelT I said for storage, I never said anything about computations Feb 11, 2014 at 16:57
  • 1
    I should note that many database drivers will automatically map a Decimal in the database to a BigDecimal in Java for you. In such cases it may become more difficult to use a custom type than just to use the natural conversion to BigDecimal provided by the system - fewer opportunities for errors.
    – user40980
    Feb 11, 2014 at 17:18
  • 1
    I have personally worked on a report for a company that had over $1 billion in sales. They would not have been happy if the report total was off by a penny. $1 billion in sales is only a mid-sized company. It's not that they care so much about a penny as it is that the CEO is going to have questions if revenue ends in .49, costs ends in .35 and profit ends in .13. So, for that matter, is the IRS. Feb 11, 2014 at 17:47

3 Answers 3

12

It all comes down to precision, and Java's BigDecimal seems the correct answer on that platform because it gives you the best support for specifying and preserving what can be highly variable precision.

A millionth of a cent is only 10-5 from a shift in payable amount, and it's not that hard to come up with a situation where that level of precision matters.

  1. Company A is publicly traded, with fifty million (5x106) shares outstanding and a current price of $10.
  2. Person B buys $1 of Company A, through a broker. They now own one-tenth of a share, or a one five-hundred-millionth of Company A. (10-7).
  3. Company A is found to be absurdly over-valued, and after a bit of a scandal winds up accepting a stock-swap purchase by Company C at a value of $1,000 (103), with each shareholder getting the equivalent number to be paid out equally to the shareholders in either cash or stock.
  4. How much cash or stock can Person B get? Note that if you get the number wrong, Person B (who happens to be an out-of-work lawyer in his 30s) can mess up the entire deal and possibly earn himself a paycheck by suing for his value lost plus legal fees.

Now, the valuation is fairly absurd on purpose, but the same "you need to get it right or it explodes" details even if the numbers are only off by a minuscule amount.

1
  • It's not just precision. In many cases there are legal requirements that determine exactly what the result has to be. Higher precision might give a more precise but different result and might not be acceptable. It's often important that results are reproducible.
    – gnasher729
    Feb 14, 2016 at 15:25
8

The right type to represent currency values depends of the application.

Two plausible choices are a type capable of exact arithmetic or a floating point type. Please remember two facts:

  1. In floating point arithmetic, usual algebraic identities (like commutativity and associativity) does not hold any more. They still hold in exact arithmetic.

  2. In exact arithmetic, it is not possible to work with functions other than polynomials, so we cannot use the square root or the exponential functions. Floating point arithmetics allows to use them.

In a double accounting personal finance software, exact arithmetic is preferrable. We expect all of the cashflows recorded to sum up to zero. Since this is an algebraic identity, we can only verify it if we use exact arithmetics. Here using a floating point would make the whole principe of double accounting useless.

In an internal software used by a clearing house, exact arithmetic is also mandatory, basically for the same reason as previously. There is a conservation principle, so that cashflows should always sum up to zero. Since the program has to satisfy an invariant of an algebraic nature, it must rely on exact arithmetics.

In a pricing or risk management software implementing methods of mathematical finance, complex computations reminescent of physics simulations are performed and expectations estimates are computed. The very nature of this problem require the use of floating point numbers.

4
  • 2
    in other words because 0.1+0.1+0.1!=0.3 floating point is not good enough Feb 11, 2014 at 20:57
  • Yeah, let's never discuss floating point and currency in the same breath, please. Feb 11, 2014 at 22:56
  • @ratchefreak In other words, it depends of the application: see my answer.
    – user40989
    Feb 12, 2014 at 7:59
  • @RossPatterson For risk management issues, floating point is appropriate. See my answer. If somnething is not clear, feel free to ask.
    – user40989
    Feb 12, 2014 at 8:00
6

I am going to make an assumption here because you don't in your question. Why is Bigdecimal the best? Because it's better then the alternatives.

Why is Bigdecimal better then Float?

Because in a float you can not precisely hold a value like decimal 0.1 . The binary representation of decimal 0.1 would be : binary 0.00011001100110011001100110011001 which if you convert it back to decimal would be: 0.0999999998603016138.

Now I want to check a >= 0.1 condition and see it fail.........

5
  • 1
    Your answer more or less assumes that the amount of money appears in an accounting software, where is key. There is applications, like pricing or risk management (i.e. finance) where using floats is mandatory because all computations are inherently inaccurate, so they should be fast. (And BTW, rely on non-polynomial functions, which you anyway cannot exactly compute.) I also do not see how your answer imprioves on DougM.
    – user40989
    Feb 12, 2014 at 12:48
  • @user40989 I think it expands on DougMs answer by giving an example where floats are inadequate even when it's not a millionth of a cent.
    – Pieter B
    Feb 12, 2014 at 12:56
  • I see. I overlooked that you are using exact comparison with floating point numbers in your message. It is often, if not always, preferable to use comparisons tolerating an error, as described by Knuth.
    – user40989
    Feb 12, 2014 at 13:36
  • 1
    I actually ran into the problem that I had 1234.10 in my (game)account and wanted to transfer all funds to another account and it refused because I "didn't have enough funds" in my account to complete the transaction. Minor nuisance ofcourse because you do 1234.09, but it surely looks unprofessional.
    – Pieter B
    Feb 12, 2014 at 14:28
  • @user40989 what do you mean by "described by Knuth", any reference?
    – croraf
    Jan 15, 2021 at 18:00

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