Search code examples
javadoublebigdecimal

Can we use double to store monetary fields and use BigDecimal for arithmetic


I know the problem with double/float, and it's recommended to use BigDecimal instead of double/float to represent monetary fields. But double/float is more effective and space-saving. Then my question is: It's acceptable to use double/float to represent monetary fields in Java class, but use BigDecimal to take care of the arithmetic (i.e. convert double/float to BigDecimal before any arithmetic) and equal-checking?

The reason is to save some space. And I really see lots of projects are using double/float to represent the monetary fields.

Is there any pitfall for this? Thanks in advance.


Solution

  • No, you can't.

    Suppose double is enough to store two values x and y. Then you convert them to safe BigDecimal and multiple them. The result is accurate, however if you store the multiplication result back in double, chances are you will loose the precision. Proof:

    double x = 1234567891234.0;
    double y = 1234567891234.0;
    System.out.println(x);
    System.out.println(y);
    
    BigDecimal bigZ = new BigDecimal(x).multiply(new BigDecimal(y));
    double z = bigZ.doubleValue();
    System.out.println(bigZ);
    System.out.println(z);
    

    Results:

    1.234567891234E12          //precise 'x'
    1.234567891234E12          //precise 'y'
     1524157878065965654042756  //precise 'x * y'
    1.5241578780659657E24      //loosing precision
    

    x and y are accurate, as well as the multiplication using BigDecimal. However after casting back to double we loose least significant digits.