Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if BigDecimal is integer value

What is an efficient way of determining whether a BigDecimal is an integer value in the mathematical sense?

At present I have the following code:

private boolean isIntegerValue(BigDecimal bd) {     boolean ret;          try {         bd.toBigIntegerExact();         ret = true;     } catch (ArithmeticException ex) {         ret = false;     }      return ret; } 

... but would like to avoid the object creation overhead if possible.

Previously I was using bd.longValueExact() which would avoid creating an object if the BigDecimal was using its compact representation internally, but obviously would fail if the value was too big to fit into a long.

like image 529
Adamski Avatar asked Jul 03 '09 11:07

Adamski


People also ask

Is BigDecimal an integer?

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.

How do I know if my value is BigDecimal?

One possiblity should be to check if scale() is zero or negative. In that case the BigDecimal should have no digits after the decimal point and the number should be a mathematical integer if I understand your question correctly.

How does BigDecimal get integer value?

intValue()converts this BigDecimal to an int. This conversion is analogous to the narrowing primitive conversion from double to short. Any fractional part of this BigDecimal will be discarded, and if the resulting "BigInteger" is too big to fit in an int, only the low-order 32 bits are returned.

How do you check BigDecimal is zero or not?

Using the compareTo Method Two BigDecimal objects that are equal in value but have a different scale (like 2.0 and 2.00) are considered equal by this method. Therefore, we can check BigDecimal. ZERO. compareTo(givenBdNumber) == 0 to decide if givenBdNumber has the value zero.


2 Answers

EDIT: As of Java 8, stripTrailingZeroes() now accounts for zero

BigDecimal stripTrailingZeros doesn't work for zero

So

private boolean isIntegerValue(BigDecimal bd) {   return bd.stripTrailingZeros().scale() <= 0; } 

Is perfectly fine now.


If you use the scale() and stripTrailingZeros() solution mentioned in some of the answers you should pay attention to zero. Zero always is an integer no matter what scale it has, and stripTrailingZeros() does not alter the scale of a zero BigDecimal.

So you could do something like this:

private boolean isIntegerValue(BigDecimal bd) {   return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0; } 
like image 87
tobi Avatar answered Sep 19 '22 14:09

tobi


Depending on the source/usage of your BigDecimal values it might be faster to check if the scale <= 0 first. If it is, then it's definitely an integer value in the mathematical sense. If it is >0, then it could still be an integer value and the more expensive test would be needed.

like image 22
Joachim Sauer Avatar answered Sep 18 '22 14:09

Joachim Sauer