Search code examples
javabigdecimalcurrency-formatting

BigDecimal round: doubleValue() vs setScale(2, BigDecimal.ROUND_HALF_UP) in price values


I am using all the time BigDecimal for prices, but I was wondering what is the best way to show this to the user.

  • Is using doubleValue() a good way?
  • Are there any differences between this two options?

Solution

  • Is using doubleValue() a good way?

    Using BigDecimal make sense if you want to avoid using double (or you want to control how your numbers are formatted). If you mix BigDecimal and double I don't see the point. You may as well using double the whole time and simplify your code.

    If you want to turn the value into a String, use toString e.g.

    BigDecimal bd = ...
    System.out.println("bd: " + bd.toString());
    

    or just

    System.out.println("bd: " + bd);
    

    If you want to use double you can do

    double d = 
    System.out.printf("%.2f%n", d); // round to 2 decimal places
    

    An example of why BigDecimal can be more error prone that double. Both of these answers are wrong, but in the case of BigDecimal it's not obvious, either in code or the result which looks fine

    System.out.println(BigDecimal.valueOf(1.00)
                                 .divide(BigDecimal.valueOf(49), 2, BigDecimal.ROUND_HALF_UP)
                                 .multiply(BigDecimal.valueOf(49)));
    System.out.println(1.00 / 49 * 49);
    

    prints

    0.98
    0.9999999999999999
    

    You can fix both code, but the fact there is a problem in the first case is easily missed. Hint: using BigDecimal.valueOf is not the issue. The more verbose the code (the more symbols you use), the harder it is to see the important details.