Can some one explain why I get 0 as result for the first line?
System.out.println((new BigDecimal("1.0E+8")).divide(new BigDecimal(100000000), BigDecimal.ROUND_HALF_UP));
System.out.println((new BigDecimal("1.0E+8")).subtract(BigDecimal.ONE).divide(new BigDecimal(100000000), BigDecimal.ROUND_HALF_UP));
0E+7
1
It all has to do with the scales of the BigDecimal
s involved.
When you specify exponential format in the constructor that takes a String
, the scale may be negative. This indicates that the significant digits don't extend all the way down to unity.
BigDecimal oneEPlus8 = new BigDecimal("1.0E+8");
System.out.println(oneEPlus8.scale());
This outputs -7
.
Using the constructor that takes an int
yields a scale of 0
.
BigDecimal oneHundredMillion = new BigDecimal(100000000);
System.out.println(oneHundredMillion.scale());
This outputs 0
.
When you divide
BigDecimal
s, the quotient takes the scale of the object on which divide
is called. So, the quotient's scale is also -7
. The result was calculated to be 1
, but in the scale of -7
, rounding only gives two options: 0
or 10000000
, so ROUND_HALF_UP
rounds to 0
, giving output of 0E+7
.
When you subtract
BigDecimal
s, the difference takes the maximum of the scales of the numbers being subtracted. So, the difference's scale is 0
. The result is calculated to be 1
, and the scale of 0
doesn't force a rounding here. The output is 1
.
To get the result 1
without having to subtract 1
, you can subtract 0
, or you can call setScale(0)
on oneEPlus8
.
oneEPlus8 = oneEPlus8.setScale(0);
System.out.println(oneEPlus8.divide(oneHundredMillion, BigDecimal.ROUND_HALF_UP));
This outputs:
1
As an aside, you can use divide(BigDecimal, RoundingMode)
to divide specifying a RoundingMode
enum instead of the older int
constants.