2

I understand that using Double data type for Money calculations is asking for trouble so Decimal should be used instead.

I feel stupid asking this, but could there be potential problems in using the Double data type to just store or transport a Money value, so long as it is converted to a Decimal when doing calculations?

I ask this because I have an old application on my hands to maintain, and it is using Double everywhere. To save work, I would like to only refactor the parts that actually do calculations, to use Decimal instead of Double. I would like to leave the rest of it alone where it is only plumbing code for data-transfer, serialization and such.

Community
  • 1
  • 1
7wp
  • 12,082
  • 18
  • 68
  • 98

4 Answers4

4

There is a loss of precision when you store data in double not just when you retrieve it. So no, this doesn't get around your problem. You can't magically retrieve precision that has been lost.

yamen
  • 14,245
  • 3
  • 37
  • 46
  • If the values which are stored are supposed to represent values which are accurate to a penny, and if values are rounded to the nearest penny on retrieval, then unless one is working with really huge numbers, all values will be precise. Note that it's important to define the extent to which values are rounded regardless of the format one is using. Even in `decimal`, (1.0m/7.0m)*7.0m does not equal 1.0m. – supercat Jun 09 '12 at 23:40
1

The answer depends on how many significant digits you need to "transport". Decimal gives you 28 digits while Double gives you about 15 or so. So if your values are in the range +/- 10 trillion (assuming 2 decimal places) you should be OK. If you use other currencies you will probably need more decimal places, so the range will be reduced to e.g. +/- 100 billion with 4 decimal places.

Ian Horwill
  • 2,741
  • 2
  • 22
  • 23
0

you shouldnt use floating point values to store monetary value..

MAybe use BigDecimal.. https://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal

ianpojman
  • 1,643
  • 1
  • 15
  • 20
-1

For example you are inserting a transaction, assuming that all the calculations are performed using decimal data-type

Amount : $45.35
 TAX   : $ 1.72
-----------------
Total  : $47.07

Now we assume that you make a sales voucher and store all the three values. While storing you convert all the three values to double. So it becomes binary floating values.

If user again tries to open the old sales voucher, you try and retrieve the three values; it may happen due to rounding and conversion (from double to decimal) you receive different values, which may appear as follows

Amount : $45.36 (//changed)
 TAX   : $ 1.72
-----------------
Total  : $47.07 (//Total sum is as stored, but when you sum 
                 //actual values retrieved, they are different.)

This is based on my experience, currently I am unable to technically explain this occurrence.

It may also happen that you store only Amount and Tax Rate but when you add them the total would be 1 cent more that the actual sales voucher which customer has:

Amount : $45.36  /*View after sales*/         Amount : $45.35  /*What customer's*/
 TAX   : $ 1.72                                TAX   : $ 1.72  /*voucher says:*/
-----------------                            -----------------
Total  : $47.07                               Total  : $47.07
Marshal
  • 6,233
  • 12
  • 52
  • 86
  • Ah - no, sorry. Seriously. Double may not be EXACT, but if you store a 4 significant digit number and reload it and it rounds wrong on the 4th digit - while double storeds 15 digits - something is SERIOUSLY wrong. Like you are rounting up always. THIS example is BAD. – TomTom May 03 '12 at 04:55
  • @TomTom: We don't know what exact rounding and conversion method developer uses. This is what to be taken care of. Although I said, I am technically not able to explain this error. But it happens only when we try to store floating to decimal types and perform operations like rounding, dividing, multiplying etc while display. – Marshal May 03 '12 at 04:59
  • We do. 45.35 to 25.35 is a broken routing method. – TomTom May 03 '12 at 05:33