BigDecimal 1.0E+8 / 100000000 ROUND_HALF_UP 为 0

BigDecimal 1.0E+8 / 100000000 with ROUND_HALF_UP is 0

谁能解释一下为什么第一行的结果是 0?

System.out.println((new BigDecimal("1.0E+8")).divide(new BigDecimal(100000000), BigDecimal.ROUND_HALF_UP));
System.out.println((new BigDecimal("1.0E+8")).subtract(BigDecimal.ONE).divide(new BigDecimal(100000000), BigDecimal.ROUND_HALF_UP));

0E+7
1

这一切都与所涉及的 BigDecimal 尺度 有关。

当您在 constructor that takes a String 中指定指数格式时,比例可能为负数。这表明有效数字不会一直向下延伸到统一。

BigDecimal oneEPlus8 = new BigDecimal("1.0E+8");
System.out.println(oneEPlus8.scale());

这输出 -7.

使用 constructor that takes an int 产生 0 的比例。

BigDecimal oneHundredMillion = new BigDecimal(100000000);
System.out.println(oneHundredMillion.scale());

这输出 0.

当您 divide BigDecimals 时,商采用调用 divide 的对象的比例。所以,商的比例也是-7。计算出来的结果是1,但是在-7的尺度下,四舍五入只给了两个选项:0或者10000000,所以ROUND_HALF_UP四舍五入到0,给出 0E+7.

的输出

当你subtract BigDecimals时,差值取被减数字的最大值。因此,差异的比例是 0。结果计算为10的比例这里不强制四舍五入。输出为 1.

要获得结果 1 而不必减去 1,您可以减去 0,或者您可以在 oneEPlus8 上调用 setScale(0)

oneEPlus8 = oneEPlus8.setScale(0);
System.out.println(oneEPlus8.divide(oneHundredMillion, BigDecimal.ROUND_HALF_UP));

这输出:

1

顺便说一句,您可以使用 divide(BigDecimal, RoundingMode) 来划分指定 RoundingMode 枚举而不是旧的 int 常量。