-2

it's pretty clear why double & co. are not a good choice when it comes to handling currency. I'm wondering though, since the issue only arises when calculations are performed on the value, am I correct by assuming that there is no problem at all to just store a currency value in a double?

For example: 1. Value gets loaded from any given source into a double 2. Value gets modified, directly typed in by the user. 3. Value gets stored to disk in a suitable format.

In the above example the double is just a way to store the value in memory, and thus shouldn't present any of the problems that arise if calculates are performed on the value. Is this correct?

And, if correct, wouldn't it be better to use currency specific types, only when performing calculations? Instead of loading 1000 BigDecimals from a database one could load 1000 doubles. Then, when necessary, define a BigDecimal, do the calculations and just keep the resulting double in memory.

r41n
  • 908
  • 7
  • 18
  • 2
    No. When you convert your `double` to a `BigDecimal`, you won't get the value you expect. Storing a currency in a `double` makes it wrong immediately, so don't do it if you're going to be calculating with it later. Unless of course, the error that is introduced is not of concern to the requirements of your program. – Dawood ibn Kareem Nov 15 '14 at 13:15
  • 2
    If you are careful enough and perform proper rounding while converting to `BigDecimal`, and you never need more than 14 significant digits, and you always know how many digits to round to, then your approach would be workable. It would still be quite fragile, though. – Marko Topolnik Nov 15 '14 at 13:19

3 Answers3

2

No, it still causes problems, even if you don't perform any calculations. The problem is that the value you store might not be exactly representable as a double, so even if you just store it and read it back, you might not get back what you stored.

If you store 0.1 in a double, for instance, you'll find it's not actually 0.1 stored at all, because you can't represent 0.1 exactly in binary.

chiastic-security
  • 20,430
  • 4
  • 39
  • 67
  • But you can *round* safely back to 0.1. So if you know what precision to round back to, this could work. – Marko Topolnik Nov 15 '14 at 13:19
  • @MarkoTopolnik sure. I suppose it depends on the exact workflow. Even if it works for now, it seems like storing up trouble for later down the line when something changes. I wouldn't touch it. – chiastic-security Nov 15 '14 at 13:21
  • 1
    Exactly, that's what I wrote in my comment to the question. There are too many ifs for it to pay off. It's still good to know where exactly the limitations are. – Marko Topolnik Nov 15 '14 at 13:22
  • You could always do `new BigDecimal(Double.toString(myDouble))` which ought to be fairly reliable. – Dawood ibn Kareem Nov 15 '14 at 13:38
2

No. A double is never the correct type to store a currency value. Doubles are floating point values, that is, they are basically numbers of the form x * 2^y, where x and y are integers. Thus, some values, such as 0.10 (10 cents) have no exact representation as a double.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
Hoopje
  • 12,677
  • 8
  • 34
  • 50
1

The problem here is that when you save say 10.12 in a double variable it may not have a exact double representation, so the java runtime will save it as a closest possible double representation, say 10.1199999999999 or 10.1200000000001 (just an example, I am not sure, have to test). So you get the point, as soon as you put the value in a double variable the currency value is approximated. However, that being said, you can still use a double for calculations and then use appropriate formatting while printing out the values or writing to file, such that the non-significant digits are hidden, depending on your application.

Sourabh Bhat
  • 1,793
  • 16
  • 21