将BigDecimal转换为Integer

时间:2010-10-28 13:56:52

标签: java integer casting bigdecimal

我有Hibernate方法,它返回一个BigDecimal。 我有另一个API方法,我需要传递该数字但它接受Integer作为参数。我无法更改两种方法的返回类型或变量类型。

现在如何将BigDecimal转换为Integer并将其传递给第二个方法?

有没有办法解决这个问题?

8 个答案:

答案 0 :(得分:195)

您可以拨打myBigDecimal.intValueExact()(或只是intValue()),如果您丢失信息,它甚至会抛出异常。返回一个int但是autoboxing负责处理。

答案 1 :(得分:32)

您能否保证BigDecimal永远不会包含大于Integer.MAX_VALUE的值?

如果是,那么这是您的代码调用intValue

Integer.valueOf(bdValue.intValue())

答案 2 :(得分:18)

<强> TL; DR

使用其中一种来满足普遍转换需求

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

<强>推理

答案取决于要求是什么以及如何回答这些问题。

  • BigDecimal可能会有非零小数部分吗?
  • BigDecimal可能不符合Integer范围吗?
  • 您希望将非零小数部分舍入或截断吗?
  • 您希望将非零小数部分舍入?

如果您对前两个问题的回答为“否”,则可以像其他人建议的那样使用BigDecimal.intValueExact(),并在发生意外情况时让它爆炸。

如果您对问题编号2没有绝对100%的信心,那么intValue() 总是错误答案。

让它变得更好

让我们根据其他答案使用以下假设。

  • 我们可以丢失精度并截断值,因为那是intValueExact()和自动拳击
  • BigDecimal大于Integer范围时,我们希望抛出一个异常,因为除非你有一个非常特殊的环绕需要,当你放弃高 - 订单位。

鉴于这些参数,intValueExact()如果我们的小数部分不为零,则在我们不希望它时抛出异常。另一方面,intValue()如果BigDecimal太大,则不会引发异常。

为了充分利用这两个方面,先将BigDecimal四舍五入,然后进行转换。这也有助于您更好地控制舍入过程。

Spock Groovy测试

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()
}

答案 3 :(得分:17)

好吧,你可以致电BigDecimal.intValue()

  

将此BigDecimal转换为int。这种转换类似于Java语言规范中定义的从double到short的缩小原语转换:此BigDecimal的任何小数部分都将被丢弃,如果生成的“BigInteger”太大而不适合int,则只有低 - 返回32位。请注意,此转换可能会丢失有关此BigDecimal值的整体大小和精度的信息,并返回具有相反符号的结果。

如果您使用的是最新版本的Java,则可以显式调用Integer.valueOf(int)或让自动装箱为您执行此操作。

答案 4 :(得分:8)

以下应该做的诀窍:

BigDecimal d = new BigDecimal(10);
int i = d.intValue();

答案 5 :(得分:1)

您是否尝试过调用BigInteger#intValue()

答案 6 :(得分:0)

答案 7 :(得分:-4)

我发现上述内容对我不起作用。我从JTable中提取了一个单元格值,但无法转换为double或int等。我的解决方案:

Object obj = getTable().getValueAt(row, 0);

其中第0行始终是数字。希望这可以帮助任何人滚动!