将BigDecimal转换为整数
我有Hibernate方法,它返回给我一个BigDecimal。 我有另一个API方法,我需要通过该号码,但它接受Integer作为参数。我无法更改这两种方法的返回类型或变量类型。将BigDecimal转换为整数
现在如何将BigDecimal转换为Integer并将其传递给第二个方法?
有没有办法呢?
您能否保证BigDecimal
永远不会包含大于Integer.MAX_VALUE
的值?
如果是的话,那么这里是你的代码中调用intValue
:
Integer.valueOf(bdValue.intValue())
之后应该做的伎俩:
BigDecimal d = new BigDecimal(10);
int i = d.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
范围? - 要非零小数部分圆整还是截断?
- 您认为非零小数部分圆整吗?
如果您对前2个问题回答“否”,您可以像其他人所建议的那样使用BigDecimal.intValueExact()
,并在意外发生时让它爆炸。
如果你对问题2号不是绝对100%的信心,那么intValue()
是总是错误的答案。
使之更好
让我们使用基于其他的答案如下假设。
- 我们都还可以与丢失精度和截断值,因为这就是
intValueExact()
和自动装箱做 - 我们希望抛出一个异常时,该
BigDecimal
比Integer
范围更大,是因为别的更是疯狂,除非你有一个非常具体的需要,当你放弃高位时发生。
鉴于这些参数,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()
}
我发现上面并没有为我工作。我拉着从JTable中单元格的值,但不能转换为加倍或INT等我的解决办法:
Object obj = getTable().getValueAt(row, 0);
其中row 0将始终是一个数字。希望这可以帮助任何人仍然滚动!
我更正了你的标题。这是*转换,*不*铸造。* – EJP 2010-10-29 00:32:17