## Converting BigDecimal to Integer

### Question

I have Hibernate method which returns me a BigDecimal. I have another API method to which I need to pass that number but it accepts Integer as parameter. I cannot change return types or variable types of both methods.

Now how to convert the BigDecimal into Integer and pass it to second method?

Is there a way out of this?

2010/10/29
1
136
10/29/2010 12:31:59 AM

You would call `myBigDecimal.intValueExact()` (or just `intValue()`) and it will even throw an exception if you would lose information. That returns an int but autoboxing takes care of that.

2015/03/01
211
3/1/2015 10:54:23 PM

Can you guarantee that the `BigDecimal` will never contain a value larger than `Integer.MAX_VALUE`?

If yes, then here's your code calling `intValue`:

``````Integer.valueOf(bdValue.intValue())
``````
2015/03/01

TL;DR

Use one of these for universal conversion needs

``````//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
``````

Reasoning

The answer depends on what the requirements are and how you answer these question.

• Will the `BigDecimal` potentially have a non-zero fractional part?
• Will the `BigDecimal` potentially not fit into the `Integer` range?
• Would you like non-zero fractional parts rounded or truncated?
• How would you like non-zero fractional parts rounded?

If you answered no to the first 2 questions, you could just use `BigDecimal.intValueExact()` as others have suggested and let it blow up when something unexpected happens.

If you are not absolutely 100% confident about question number 2, then `intValue()` is always the wrong answer.

Making it better

Let's use the following assumptions based on the other answers.

• We are okay with losing precision and truncating the value because that's what `intValueExact()` and auto-boxing do
• We want an exception thrown when the `BigDecimal` is larger than the `Integer` range because anything else would be crazy unless you have a very specific need for the wrap around that happens when you drop the high-order bits.

Given those params, `intValueExact()` throws an exception when we don't want it to if our fractional part is non-zero. On the other hand, `intValue()` doesn't throw an exception when it should if our `BigDecimal` is too large.

To get the best of both worlds, round off the `BigDecimal` first, then convert. This also has the benefit of giving you more control over the rounding process.

Spock Groovy Test

``````void 'test BigDecimal rounding'() {
given:
BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99)
BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99)
BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000")
String decimalAsBigIntString = decimal.toBigInteger().toString()
String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString()
String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString()

expect: 'decimals that can be truncated within Integer range to do so without exception'
//GOOD: Truncates without exception
'' + decimal.intValue() == decimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
// decimal.intValueExact() == decimalAsBigIntString
//GOOD: Truncates without exception
'' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString

and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
//'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString

and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//'' + reallyHuge.intValue() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString

and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal'
//decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact()
}
``````
2015/03/11

Well, you could call `BigDecimal.intValue()`:

Converts this BigDecimal to an int. This conversion is analogous to a narrowing primitive conversion from double to short as defined in the Java Language Specification: 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. Note that this conversion can lose information about the overall magnitude and precision of this BigDecimal value as well as return a result with the opposite sign.

You can then either explicitly call `Integer.valueOf(int)` or let auto-boxing do it for you if you're using a sufficiently recent version of Java.

2010/10/28

Following should do the trick:

``````BigDecimal d = new BigDecimal(10);
int i = d.intValue();
``````
2010/10/28

Have you tried calling BigInteger#intValue() ?

2010/10/28