将 BigDecimal 转换为 Integer
Posted
技术标签:
【中文标题】将 BigDecimal 转换为 Integer【英文标题】:Converting BigDecimal to Integer 【发布时间】:2011-05-01 21:51:01 【问题描述】:我有 Hibernate 方法,它返回一个 BigDecimal。 我有另一个 API 方法,我需要将该数字传递给它,但它接受 Integer 作为参数。我无法更改这两种方法的返回类型或变量类型。
现在如何 并将其传递给第二个方法?
有办法解决吗?
【问题讨论】:
我更正了您的标题。这是转换,而不是转换。 【参考方案1】:您会调用myBigDecimal.intValueExact()
(或只是intValue()
),如果您丢失信息,它甚至会抛出异常。这会返回一个 int,但自动装箱会解决这个问题。
【讨论】:
intValueExact()
是一个很好的推荐;它是在 1.5 中添加的
打电话给intValue()
是危险的,除非你100%赌上你的生命,肯定这个数字在Integer
范围内。
这有意义吗:“Integer.valueOf(myBigDecimal.intValueExact())”?【参考方案2】:
你能保证BigDecimal
永远不会包含大于Integer.MAX_VALUE
的值吗?
如果是,那么这是您调用 intValue
的代码:
Integer.valueOf(bdValue.intValue())
【讨论】:
是的。我猜它不会包含比 Integer.MAX_VALUE 更大的值 除了获取对象而不是原始对象之外,没有理由执行 valueOf 吗? 我会说这应该是官方答案,因为 a.提到限制,b。防止自动装箱。【参考方案3】: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
修整,然后再进行转换。这也有利于您更好地控制舍入过程。
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()
【讨论】:
【参考方案4】:嗯,你可以拨打BigDecimal.intValue()
:
将此 BigDecimal 转换为 int。这种转换类似于 Java 语言规范中定义的从 double 到 short 的缩小原语转换:BigDecimal 的任何小数部分都将被丢弃,如果生成的“BigInteger”太大而无法放入 int,则只有低-order 32 位被返回。请注意,此转换可能会丢失有关此 BigDecimal 值的整体大小和精度的信息,并返回带有相反符号的结果。
然后,如果您使用的是足够新的 Java 版本,您可以显式调用 Integer.valueOf(int)
或让自动装箱为您执行此操作。
【讨论】:
【参考方案5】:以下应该可以解决问题:
BigDecimal d = new BigDecimal(10);
int i = d.intValue();
【讨论】:
【参考方案6】:你试过打电话给BigInteger#intValue()吗?
【讨论】:
【参考方案7】:见BigDecimal#intValue()
【讨论】:
【参考方案8】:我发现上述方法对我不起作用。我正在从 JTable 中提取单元格值,但无法转换为 double 或 int 等。我的解决方案:
Object obj = getTable().getValueAt(row, 0);
第 0 行总是一个数字。希望这对仍在滚动的人有所帮助!
【讨论】:
以上是关于将 BigDecimal 转换为 Integer的主要内容,如果未能解决你的问题,请参考以下文章
java - 如何将浮点数转换为 BigDecimal? [复制]