当被删除的数字不大于 2(非零)时,我无法理解 BigDecimal Roundingmode HALF_EVEN 的行为。 根据 docs ,使用 HALF_EVEN 舍入,当丢弃的左侧数字为偶数时,它是 HALF_DOWN 情况,因此左侧数字不会递增。因此,标度为 2 的“1.3651”应该得到“1.36”,但结果是“1.37”。看看 BigDecimal 代码,似乎如果由被删除的数字形成的数字大于 50,它会增加一个增量,这就是为什么我得到的结果为“1.37”。
private static int longCompareMagnitude(long x, long y) {
if (x < 0)
x = -x;
if (y < 0)
y = -y;
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
解释上面代码片段中的X和Y
x : 2*(不由要删除的数字组成)。 例如1.3753 和比例 2,此处 x 为 53*2 = 106 y :它是丢弃数字长度的桶[1,10,100]。这里 Y 是 100
int drop = checkScale((long) oldScale - newScale);
// old scale is precision on current number(decimal places after . : 4)
y = LONG_TEN_POWERS_TABLE[drop]
所以 x==y 的情况是当要删除的数字是 5 或 50 等时。 否则,如果由删除的数字组成的数字大于 50,它将始终加 1。所以下面的情况似乎按照代码工作。但文档说这是 HALF_DOWN 情况,因此不应增加[HALF_UP]
我写了以下示例来验证这一点。有人可以解释一下结果被标记为 false 的最后 2 个条目的行为吗?
Java 版本:OpenLogic-OpenJDK(内部版本 11.0.16+8)、Corretto-17.0.12.7.1
@Test
fun bigDecimalTest() {
printResult("Round up ", "1.176", "1.18", 2)
//4 being dropped is less than 5, doesn't qualify for round up
printResult("Round down", "1.174", "1.17", 2)
println("Equidistant round off with HALF EVEN rounding")
printResult("HALF up case", "1.175", "1.18", 2)
printResult("HALF up case", "1.3753", "1.38", 2)
printResult("HALF down case", "1.365", "1.36", 2)
printResult("HALF down case with 2 digits dropped", "1.3650", "1.36", 2)
println("half down not happening when number formed by digits to be dropped is 5/50")
printResult("HALF down case with 2 digits dropped", "1.3651", "1.36", 2)
printResult("HALF down case with 2 digits dropped", "1.3653", "1.36", 2)
}
private fun printResult(message: String, input: String, expected: String, scale: Int) {
val actual = BigDecimal(input).setScale(scale, RoundingMode.HALF_EVEN)
val result = BigDecimal(expected) == actual
println("$message, scale: $scale: input: $input, expected :$expected, actual= $actual, Matched= $result")
}
输出:
Round up , scale: 2: input: 1.176, expected :1.18, actual= 1.18, Matched= true
Round down, scale: 2: input: 1.174, expected :1.17, actual= 1.17, Matched= true
Equidistant round off with HALF EVEN rounding
HALF up case, scale: 2: input: 1.175, expected :1.18, actual= 1.18, Matched= true
HALF up case, scale: 2: input: 1.3753, expected :1.38, actual= 1.38, Matched= true
HALF down case, scale: 2: input: 1.365, expected :1.36, actual= 1.36, Matched= true
HALF down case with 2 digits dropped, scale: 2: input: 1.3650, expected :1.36, actual= 1.36, Matched= true
half down not happening when number formed by digits to be dropped is 5/50
HALF down case with 2 digits dropped, scale: 2: input: 1.3651, expected :1.36, actual= 1.37, Matched= false
HALF down case with 2 digits dropped, scale: 2: input: 1.3653, expected :1.36, actual= 1.37, Matched= false