I know that I can use BigDecimal.divide()
method to set a fixed precision:
BigDecimal a1 = new BigDecimal(1);
BigDecimal a2 = new BigDecimal(3);
BigDecimal division = a1.divide(a2,5,1); //equals 0.33333
But if the division result is exact:
BigDecimal a1 = new BigDecimal(1);
BigDecimal a2 = new BigDecimal(4);
BigDecimal division = a1.divide(a2,5,1); //equals 0.25000
How can I set the division result so if the division ends with an exact result, it will just give the output of 0.25 instead of 0.25000?
I've also tried to not specifying a precision by doing:
BigDecimal division = a1.divide(a2);
it succeeds in giving the result 0.25
when doing 1/4
, but when it does division like 1/3
or 2/3
it results in a runtime ArithmeticException
.
a1
and a2
are instantiated from user input.
Is there any way to solve this?
You get an ArithmeticException
as described in BigDecimal.divide(BigDecimal)
- "if the exact quotient does not have a terminating decimal expansion" because to properly represent the result of 1/3
would take infinite memory. By using BigDecimal.divide(BigDecimal,int,RoundingMode)
you explicitly set what precision you'll tolerate, meaning any division can be approximated in-memory.
For consistency this version of division always sets the scale to what you specify, even if the value can be accurately represented with less precision. If it didn't, it would be difficult for you to reason about how precise any future computations using that result will be.
To reduce your precision use .stripTrailingZeros()
; this effectively reduces the scale to the minimum possible. Do this as late in the process as possible (i.e. right before you print) to maintain that consistency I mentioned above.
You may also want .toPlainString()
if you're trying to display these values nicely, since .stripTrailingZeros()
on its own will display 100
as 1E+2
.