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
A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale.
intValue() is an in-built function which converts this BigDecimal to an integer value. This function discards any fractional part of this BigDecimal. If the result of the conversion is too big to be represented as an integer value, the function returns only the lower-order 32 bits.
If you are using type BigDecimal, then its default value is null (it is object, not primitive type), so you get [1] automatically.
By default, BigDecimal numbers have “unlimited” precision. In fact, the maximum unscaled value is equal to 2^Integer.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With