Java BigDecimal 运算 "arbitrarily" 显示不正确的小数位数

Java BigDecimal operations "arbitrarily" showing incorrect number of decimal places

我正在尝试使用 BigDecimal class 解决一个练习,但对于某些值,它不遵守要显示的正确小数位数。 对于 5.0 到 12.5 的值,它显示额外的小数位。知道为什么吗?提前致谢。

这是代码的改编版本:

MathContext mc = new MathContext(2, RoundingMode.UP);

BigDecimal min = new BigDecimal("2.00");
BigDecimal adt = new BigDecimal("0.50");
BigDecimal lim = new BigDecimal("3.00");

for (float f = 5f; f <= 30f ; f += 0.5f) {
    String s = Float.toString(f);
    BigDecimal hours = new BigDecimal(s);
    BigDecimal charge = min.add(hours.subtract(lim).round(mc).multiply(adt));
    System.out.println(f + " = " + charge);
}

输出:

5.0 = 3.000
5.5 = 3.250
6.0 = 3.500
6.5 = 3.750
7.0 = 4.000
7.5 = 4.250
8.0 = 4.500
8.5 = 4.750
9.0 = 5.000
9.5 = 5.250
10.0 = 5.500
10.5 = 5.750
11.0 = 6.000
11.5 = 6.250
12.0 = 6.500
12.5 = 6.750
13.0 = 7.00
13.5 = 7.50
14.0 = 7.50
14.5 = 8.00
15.0 = 8.00
15.5 = 8.50
16.0 = 8.50
16.5 = 9.00
17.0 = 9.00
17.5 = 9.50
18.0 = 9.50
18.5 = 10.00
19.0 = 10.00
19.5 = 10.50
20.0 = 10.50
20.5 = 11.00
21.0 = 11.00
21.5 = 11.50
22.0 = 11.50
22.5 = 12.00
23.0 = 12.00
23.5 = 12.50
24.0 = 12.50
24.5 = 13.00
25.0 = 13.00
25.5 = 13.50
26.0 = 13.50
26.5 = 14.00
27.0 = 14.00
27.5 = 14.50
28.0 = 14.50
28.5 = 15.00
29.0 = 15.00
29.5 = 15.50
30.0 = 15.50

这个问题很可能是对MathContext的误解。对于 MathContext(2, RoundingMode.UP),您不是在说“我想要小数点后两位 ”,而是在说“我想将数字的精度降低到 2 位".

如果你看一下你的数字,小数位数(小数位数)是 2,其中 hours - lim >= 10

如果你仔细看看hours=12.5hours=13.0

这两个例子
//hours = 12.5:
var subtract = hours.subtract("3.00"); // 12.5 - 3.00 = 9.50 (subtract.scale = 2)
var round = subtract.round(mc); // 9.5 (round.scale = 1)
var result = round.multiply("0.50") // 9.5 * 0.50 = 4.750 (result.scale = round.scale + subtract.scale = 3)
//hours = 13.0:
var subtract = hours.subtract("3.00"); // 13.0 - 3.00 = 10.00 (subtract.scale = 2)
var round = subtract.round(mc); // 10 (round.scale = 0)
var result = round.multiply("0.50") // 10 * 0.50 = 5.00 (result.scale = round.scale + subtract.scale = 2)

你看四舍五入小数的小数位数一变成>=10就变成0了。乘法结果的小数位数永远是两个被乘数小数位数之和。

要设置 BigDecimal 的比例,请使用 BigDecimal.setScale(int, RoundingMode) 而不是 MathContext