将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将始终是一个数字。 希望这有助于任何人仍然滚动!