当前位置: 首页 > 面试题库 >

仅Java 8的NumberFormat舍入问题

孟开宇
2023-03-14
问题内容

有人可以向我解释以下代码的原因:

public class Test {
    public static void main(String... args) {
        round(6.2088, 3);
        round(6.2089, 3);
    }

    private static void round(Double num, int numDecimal) {
        System.out.println("BigDecimal: " + new BigDecimal(num).toString());

        // Use Locale.ENGLISH for '.' as decimal separator
        NumberFormat nf = NumberFormat.getInstance(Locale.ENGLISH);
        nf.setGroupingUsed(false);
        nf.setMaximumFractionDigits(numDecimal);
        nf.setRoundingMode(RoundingMode.HALF_UP);

        if(Math.abs(num) - Math.abs(num.intValue()) != 0){
            nf.setMinimumFractionDigits(numDecimal);
        }

        System.out.println("Formatted: " + nf.format(num));
    }
}

给出以下输出?

[me@localhost trunk]$ java Test
BigDecimal: 6.208800000000000096633812063373625278472900390625
Formatted: 6.209
BigDecimal: 6.208899999999999863575794734060764312744140625
Formatted: 6.208

如果您看不到它,则:“ 6.2089”舍入为3位数字将输出为“ 6.208”,而“ 6.2088”将输出为“ 6.209”。少即是多?

使用Java 5、6或7时,效果很好,但是此Java 8给了我奇怪的输出。Java版本:

[me@localhost trunk]$ java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) Server VM (build 25.5-b02, mixed mode)

编辑:这是Java 7的输出:

[me@localhost trunk]$ java Test
BigDecimal: 6.208800000000000096633812063373625278472900390625
Formatted: 6.209
BigDecimal: 6.208899999999999863575794734060764312744140625
Formatted: 6.209

Java 7版本:

[me@localhost trunk]$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) Server VM (build 24.51-b03, mixed mode)

问题答案:

我可以将此问题归类到java.text.DigitList522行。

这种情况是,它认为十进制数字6.0289已经舍入(与等效BigDecimal表示形式相比是正确的6.208899…),并决定不再舍入。问题在于,只有在舍入后的数字为的情况下才可以做出此决定5,而不是大于的情况下才有意义5。注意代码是如何HALF_DOWN正确区分digit=='5'digit>'5'情况。

显然,这是一个错误,并且由于一个事实,即执行类似正确操作(仅针对另一个方向)的代码恰好位于损坏的错误代码的下面,因此这是一个奇怪的错误。

        case HALF_UP:
            if (digits[maximumDigits] >= '5') {
                // We should not round up if the rounding digits position is
                // exactly the last index and if digits were already rounded.
                if ((maximumDigits == (count - 1)) &&
                    (alreadyRounded))
                    return false;

                // Value was exactly at or was above tie. We must round up.
                return true;
            }
            break;
        case HALF_DOWN:
            if (digits[maximumDigits] > '5') {
                return true;
            } else if (digits[maximumDigits] == '5' ) {
                if (maximumDigits == (count - 1)) {
                    // The rounding position is exactly the last index.
                    if (allDecimalDigits || alreadyRounded)
                        /* FloatingDecimal rounded up (value was below tie),
                         * or provided the exact list of digits (value was
                         * an exact tie). We should not round up, following
                         * the HALF_DOWN rounding rule.
                         */
                        return false;
                    else
                        // Value was above the tie, we must round up.
                        return true;
                }

                // We must round up if it gives a non null digit after '5'.
                for (int i=maximumDigits+1; i<count; ++i) {
                    if (digits[i] != '0') {
                        return true;
                    }
                }
            }
            break;

另一个数字没有发生这种情况的原因不是6.2088四舍五入的结果(再次与BigDecimal输出进行比较6.208800…)。因此,在这种情况下它将四舍五入。



 类似资料:
  • 有人能向我解释为什么以下代码: 给出以下输出? 以防您没有看到:“6.2089”四舍五入为3位给出输出“6.208”,而“6.2088”给出“6.209”作为输出。少即是多? 当使用Java 5、6或7时,结果很好,但这个Java 8给了我这个奇怪的输出。Java版本: 编辑:这是Java7的输出: Java7版本:

  • 我尝试使用scale=3和HALF\u向上舍入模式舍入0.14049,希望看到舍入值=0.141,但得到的是0.140。 根据我的理解,最后一个十进制数字9应该将4到5四舍五入,当使用小数点3时,应该将0到1四舍五入,我应该看到0.141。 这是BigDecimal setScale方法中的错误还是我对舍入的期望是错误的。如何获得类似于0.141而不是0.140的舍入值?

  • java.text.NumberFormat类用于根据特定的Locale格式化数字和货币。 数字格式因国家/地区而异。 例如,在丹麦,使用逗号将数字的分数与整数部分分开,而在英格兰,它们使用点作为分隔符。 示例 - 格式编号 在此示例中,我们根据美国语言环境和丹麦语区域设置格式化数字。 IOTester.java import java.text.NumberFormat; import java

  • 问题内容: 我正在尝试执行 累积乘法 。我正在尝试两种方法来做到这一点 样本数据: 注意:列中 的数据永远不会是整数,并且值将具有小数部分。为了显示近似问题,我将示例值保留为整数。 方法1:EXP + LOG + SUM()结束(排序依据) 在这种方法中,我使用技术来查找累积乘法。在这种方法中,数值不准确;结果中存在一些舍入和近似问题。 结果: 方法2:传统乘法(递归CTE) 该方法完美地工作,没

  • 我有一个由数字组成的数据集。我想在一份报告中陈述这一点。我已经设法生成了一个具有以下格式的报告。这有点类似于会计中的试算表。但事实并非如此!表中的数据在其值中有4个小数点。但在报告中,它应该四舍五入到小数点后两位。报告还必须准确,因此需要使用。 基于@marciob、@user3679868和@joopeggen的编辑3决定根据舍入值进行计算。差额。047(.56-.553)显然被冲销了(审计标准

  • 问题内容: 这是小代码来说明我所看到的 打印: 我要打印 我需要做什么? 问题答案: 在使用之前添加以下行: 查看其他舍入模式,看看哪种最适合您。 注意:此方法仅在JDK 1.6或更高版本中有效