Java 将 BigDecimal 转换为整数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4043579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 10:52:32  来源:igfitidea点击:

Converting BigDecimal to Integer

javaintegercastingbigdecimal

提问by Vishal

I have Hibernate method which returns me a BigDecimal. I have another API method to which I need to pass that number but it accepts Integer as parameter. I cannot change return types or variable types of both methods.

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

Now how to convert the BigDecimal into Integer and pass it to second method?

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

Is there a way out of this?

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

采纳答案by willcodejavaforfood

You would call myBigDecimal.intValueExact()(or just intValue()) and it will even throw an exception if you would lose information. That returns an int but autoboxing takes care of that.

您会调用myBigDecimal.intValueExact()(或仅调用intValue()),如果您丢失信息,它甚至会抛出异常。这会返回一个 int 但自动装箱会解决这个问题。

回答by Anon

Can you guarantee that the BigDecimalwill never contain a value larger than Integer.MAX_VALUE?

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

If yes, then here's your code calling intValue:

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

Integer.valueOf(bdValue.intValue())

回答by Gareth Davis

Following should do the trick:

以下应该可以解决问题:

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

回答by Jon Skeet

Well, you could call BigDecimal.intValue():

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

Converts this BigDecimal to an int. This conversion is analogous to a narrowing primitive conversion from double to short as defined in the Java Language Specification: any fractional part of this BigDecimal will be discarded, and if the resulting "BigInteger" is too big to fit in an int, only the low-order 32 bits are returned. Note that this conversion can lose information about the overall magnitude and precision of this BigDecimal value as well as return a result with the opposite sign.

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

You can then either explicitly call Integer.valueOf(int)or let auto-boxing do it for you if you're using a sufficiently recent version of Java.

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

回答by Riduidel

Have you tried calling BigInteger#intValue()?

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

回答by Snekse

TL;DR

TL; 博士

Use one of these for universal conversion needs

使用其中之一来满足通用转换需求

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

Reasoning

推理

The answer depends on what the requirements are and how you answer these question.

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

  • Will the BigDecimalpotentially have a non-zero fractional part?
  • Will the BigDecimalpotentially not fit into the Integerrange?
  • Would you like non-zero fractional parts rounded or truncated?
  • How would you like non-zero fractional parts rounded?
  • BigDecimal潜在地具有非零小数部分?
  • 是否BigDecimal可能不适合该Integer范围?
  • 您想要四舍五入或截断的非零小数部分吗?
  • 您希望如何舍入非零小数部分?

If you answered no to the first 2 questions, you could just use BigDecimal.intValueExact()as others have suggested and let it blow up when something unexpected happens.

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

If you are not absolutely 100% confident about question number 2, then intValue()is alwaysthe wrong answer.

如果你不是绝对100%的信心问题编号2,然后intValue()一直错误的答案。

Making it better

让它变得更好

Let's use the following assumptions based on the other answers.

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

  • We are okay with losing precision and truncating the value because that's what intValueExact()and auto-boxing do
  • We want an exception thrown when the BigDecimalis larger than the Integerrange because anything else would be crazy unless you have a very specific need for the wrap around that happens when you drop the high-order bits.
  • 我们可以接受失去精度和截断值,因为这就是intValueExact()自动装箱所做的
  • 我们希望在BigDecimal大于Integer范围时抛出异常,因为除非您对丢弃高位时发生的环绕有非常特殊的需求,否则其他任何事情都会很疯狂。

Given those params, intValueExact()throws an exception when we don't want it to if our fractional part is non-zero. On the other hand, intValue()doesn't throw an exception when it should if our BigDecimalis too large.

给定这些参数,intValueExact()如果我们的小数部分非零,我们不希望它抛出异常。另一方面,intValue()如果我们BigDecimal太大,则不会在应该抛出异常时抛出异常。

To get the best of both worlds, round off the BigDecimalfirst, then convert. This also has the benefit of giving you more control over the rounding process.

要获得两全其美,BigDecimal请先将第一个四舍五入,然后再转换。这也有利于让您更好地控制舍入过程。

Spock Groovy Test

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

回答by beehive

I found that the above did not work for me. I was pulling a cell value from a JTable but could not cast to double or int etc. My solution:

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

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

where row 0 would always be a number. Hope this helps anyone still scrolling!

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