Search code examples
javadoubleguavaprecision

Sum of BigDecimal(s) created from possible null Double


In order to avoid possible loss of precision in Java operation on Double objects i.e.:

Double totalDouble = new Double(1590.0);
Double taxesDouble = new Double(141.11);
Double totalwithTaxes = Double.sum(totalDouble,taxesDouble);
//KO: 1731.1100000000001
System.out.println(totalwithTaxes); // 1731.1100000000001

I wrote this code, where totalDouble and taxesDouble could be also null:

Double totalDouble = myObject.getTotalDouble();
Double taxesDouble = myObject.getTaxesDouble();
BigDecimal totalBigDecimalNotNull = (totalDouble==null) ? BigDecimal.valueOf(0d):BigDecimal.valueOf(totalDouble);
BigDecimal taxesBigDecimalNotNull = (taxesDouble==null) ? BigDecimal.valueOf(0d):BigDecimal.valueOf(taxesDouble);
BigDecimal totalWithTaxesBigDecimal = totalBigDecimalNotNull.add(taxesBigDecimalNotNull);
System.out.println(totalWithTaxesBigDecimal);

Is there a better way (also with third part libraries i.e. guava, etc) to initialize BigDecimal in this cases (zero if Double is null and Double value otherwise)?


Solution

  • Not really. That is to say, you're still going to need to make a decision based on whether or not the value is null, but you can do it cleaner if you use the Optional pattern.

    You can change your getTotalDouble and getTaxesDouble returns to Optional<Double> instead to mititgate having to do the ternary...

    public Optional<Double> getTotalDouble() {
       return Optional.ofNullable(totalDouble);
    }
    
    public Optional<Double> getTaxesDouble() {
       return Optional.ofNullable(taxesDouble);
    }
    

    ...then, you can use the conditional evaluation provided by Optional itself to evaluate and return a default value.

    BigDecimal totalBigDecimalNotNull =
               BigDecimal.valueOf(myObject.getTotalDouble().orElse(0d));
    

    A simplification would be to return Optional<BigDecimal> instead, as opposed to transforming the value that you want in this fashion.

    As an addendum, be careful when talking about precision. There is standing advice to use either int or long instead to ensure you don't lose any coin precision.