线程 "main" java.lang.ArithmeticException 中的异常:需要舍入

Exception in thread "main" java.lang.ArithmeticException: Rounding necessary

当我尝试获取 longValueExact() 时:

BigDecimal bigDecimal = new BigDecimal(432.900).divide(new BigDecimal(1), 2, RoundingMode.FLOOR);
System.out.println(bigDecimal.longValueExact());

Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
    at java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4151)
    at java.math.BigDecimal.needIncrement(BigDecimal.java:4207)
    at java.math.BigDecimal.divideAndRound(BigDecimal.java:4115)
    at java.math.BigDecimal.setScale(BigDecimal.java:2455)
    at java.math.BigDecimal.longValueExact(BigDecimal.java:3093)
    at com.tessi.bmd.specific.actil.utils.ActilUtils.main(ActilUtils.java:1281)

new BigDecimal(432.900)

这是个坏主意。 432.900 是双重文字,因此极不可能实际表示 432.900。您使用的是 BigDecimal,因此您可能知道最多只有 2^64 个数字可以完全由 double 表示。 432.900 不是其中之一。不要使用这个构造函数——它到处都有警告。使用 new BigDecimal("432.9").

.divide(new BigDecimal(1),

好的,除以1,什么都不做。另外,为此使用 BigDecimal.ONE

该值仍然是 432.899999999999434 或诸如此类的东西。

System.out.println(bigDecimal.longValueExact());

当然这行不通 - 长整型值只能包含整数值,而 432.9(或接近该值的值)则不行。

您是否认为 432.900 只是 432900 的一种书写方式,对于某些将 . 用作千位分隔符的语言环境的人来说更易读?

. 是小数分隔符。 432.900 是一个双精度字面量,表示最接近数字 432 + 9/10ths 的可表示双精度数。如果这是你的意图,请删除 . - 如果你想为是创建一些水平 space,请使用 _ 这在数字文字上是合法的并且没有意义。

如果这不是您的问题并且您确实希望 432.9 作为一个精确的长 - 我想,回到第一个问题并开始学习 java。很快(毫无疑问,在一两天内)您将学习教程中解释原始数据类型的部分。请特别注意这一部分。

这是正常行为,因为您要显示为 long 的值具有小数部分(432.89,而不是 432.90,因为从 double 实例化 BigDecimal)所以不是整数。来自 javadoc:

Converts this BigDecimal to a long, checking for lost information. If this BigDecimal has a nonzero fractional part or is out of the possible range for a long result then an ArithmeticException is thrown.