2010-10-28 148 views
102

我有Hibernate方法,它返回给我一个BigDecimal。 我有另一个API方法,我需要通过该号码,但它接受Integer作为参数。我无法更改这两种方法的返回类型或变量类型。将BigDecimal转换为整数

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

有没有办法呢?

+4

我更正了你的标题。这是*转换,*不*铸造。* – EJP 2010-10-29 00:32:17

回答

162

你会打电话myBigDecimal.intValueExact()(或只是intValue()),它甚至会抛出一个异常,如果你会失去信息。这返回一个整数,但自动装箱处理。

+1

'intValueExact()'是一个很好的建议;它被添加到1.5中 – Anon 2010-10-28 14:08:52

+0

调用'intValue()'是危险的,除非你100%打赌你的生活,它肯定该数字在整数范围内。 – Snekse 2015-03-14 20:53:37

+1

这是否合理:“In​​teger.valueOf(myBigDecimal.intValueExact())”? – OddDev 2015-10-01 05:38:00

29

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

如果是的话,那么这里是你的代码中调用intValue

Integer.valueOf(bdValue.intValue()) 
+0

是的。我猜它不会包含比Integer更大的值.MAX_VALUE – Vishal 2010-10-28 14:04:01

+1

除了获取对象而不是原始权利之外,没有理由执行valueOf? – Basil 2014-07-18 22:08:50

+0

我会说这应该是官方答案,因为a。提到了限制,b。防止自动装箱。 – ledlogic 2015-06-26 21:31:03

5

之后应该做的伎俩:

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

嗯,你可以拨打BigDecimal.intValue()

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

然后,您可以显式调用Integer.valueOf(int)或让自动装箱为你做,如果您使用的是足够新的Java版本。

14

TL; DR

使用这些通用转换一个需要

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

推理

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

  • BigDecimal可能有一个非零小数部分?
  • BigDecimal可能不适合Integer范围?
  • 要非零小数部分圆整还是截断?
  • 您认为非零小数部分圆整吗?

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

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

使之更好

让我们使用基于其他的答案如下假设。

  • 我们都还可以与丢失精度和截断值,因为这就是intValueExact()和自动装箱做
  • 我们希望抛出一个异常时,该BigDecimalInteger范围更大,是因为别的更是疯狂,除非你有一个非常具体的需要,当你放弃高位时发生。

鉴于这些参数,intValueExact()抛出一个例外,当我们不希望它,如果我们的小数部分是非零。另一方面,如果我们的BigDecimal太大,intValue()不会抛出异常。

为了获得两全其美的效果,先将BigDecimal四舍五入,然后转换。这也有利于您更多地控制舍入过程。

斯波克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() 
} 
-2

我发现上面并没有为我工作。我拉着从JTable中单元格的值,但不能转换为加倍或INT等我的解决办法:

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

其中row 0将始终是一个数字。希望这可以帮助任何人仍然滚动!