将 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? [复制]

将 BigDecimal 转换为 Integer

将 BigDecimal 转换为 Integer 时出现问题

将具有负比例的 BigDecimal 转换为正比例

BigDecimal类的用法

Scala 将BigDecimal转换为Long