当被丢弃的数字数量不大于 1 时,BigDecimal 舍入模式 HALF_EVEN 不起作用[重复]

问题描述 投票:0回答:1

当被删除的数字不大于 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
java precision bigdecimal
1个回答
0
投票

引用您链接的docs

舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下,向偶数邻居舍入。

邻居不是等距的,因此它会选择最近的邻居。

© www.soinside.com 2019 - 2024. All rights reserved.