将BigDecimal转换为整数
我有Hibernate方法返回给我一个BigDecimal。 我有另一个API方法,我需要通过该号码,但它接受整数作为参数。 我不能改变这两种方法的返回types或variablestypes。
现在如何将BigDecimal转换为Integer并将其传递给第二个方法?
有没有办法呢?
你可以调用myBigDecimal.intValueExact()
(或者只是intValue()
),如果你会丢失信息,它甚至会抛出一个exception。 这返回一个整数,但自动装箱照顾。
你能保证BigDecimal
永远不会包含大于Integer.MAX_VALUE
的值吗?
如果是,那么这里是你的代码调用intValue
:
Integer.valueOf(bdValue.intValue())
那么,你可以调用BigDecimal.intValue()
:
将此BigDecimal转换为int。 这种转换类似于在Java语言规范中定义的从缩小到缩小的原始双重转换:这个BigDecimal的任何小数部分都将被丢弃,如果得到的“BigInteger”太大而不能放入int,只有低32位返回。 请注意,此转换可能会丢失有关此BigDecimal值的总体大小和精度的信息,并返回相反符号的结果。
然后你可以明确地调用Integer.valueOf(int)
或者让自动装箱为你做,如果你使用的是一个足够新的Java版本。
TL; DR
使用其中之一来满足通用转换需求
//Java 7 or below bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact() //Java 8 bigDecimal.toBigInteger().intValueExact()
推理
答案取决于要求是什么以及你如何回答这些问题。
-
BigDecimal
可能有一个非零小数部分? -
BigDecimal
可能不适合Integer
范围吗? - 你想非零小数部分圆形或截断?
- 您如何舍入非零小数部分?
如果对前两个问题的回答是否定的,则可以像其他人所build议的那样使用BigDecimal.intValueExact()
,并在发生意外事件时让它爆炸。
如果你对问题2没有绝对的100%信心,那么intValue()
总是错误的答案。
做得更好
让我们根据其他答案使用以下假设。
- 我们可以丢失精度和截断值,因为这是什么
intValueExact()
和自动装箱 - 当
BigDecimal
大于Integer
范围时,我们希望抛出一个exception,因为除非你有非常特殊的需要,否则当你删除高位时,会发生其他情况。
给定这些参数,如果我们的小数部分不为零, intValueExact()
会抛出一个exception。 另一方面,如果我们的BigDecimal
太大, intValue()
不会抛出exception。
为了得到两全其美,先把BigDecimal
取整,然后转换。 这也有利于您更多地控制舍入过程。
Spock Groovytesting
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' //BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648 //'' + 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' //BAD: hugeDecimal.intValue() is 0 //'' + 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() }
以下应该做的伎俩:
BigDecimal d = new BigDecimal(10); int i = d.intValue();
你有没有试过调用BigInteger#intValue() ?
请参阅BigDecimal#intValue()
我发现上述不适合我。 我从一个JTable拉单元格值,但不能强制转换为double或int等。我的解决scheme:
Object obj = getTable().getValueAt(row, 0);
行0将始终是一个数字。 希望这有助于任何人仍然滚动!