【问题标题】:Confused by DecimalFormat/RoundingMode.Down functionality for edge cases对边缘情况的 DecimalFormat/RoundingMode.Down 功能感到困惑
【发布时间】:2017-10-13 19:36:17
【问题描述】:

基于this stackoverflow post,我希望以下打印出 0.59 而不是 0.60。

import java.math.RoundingMode;
import java.text.DecimalFormat;

public class Test {
    public static void main(String[] args) {
        double toFormat = 0.6;
        DecimalFormat formatter = new DecimalFormat("########0.00");
        formatter.setRoundingMode(RoundingMode.DOWN);
        System.out.println(formatter.format(toFormat)); // 0.60
    }
}

0.60 最接近的浮点表示是 0.59999999999999997779553950749686919152736663818359375,低于 0.6。在 Java 8 中将 DecimalFormat 设置为 RoundingMode.DOWN,为什么不将其向下舍入为 0.59?

【问题讨论】:

    标签: java floating-point decimalformat


    【解决方案1】:

    因为格式化代码知道double 的精度。

    参见source code 中方法shouldRoundUp(...) 在类java.text.DigitList 中的注释:

    为避免在转换时出现错误的双舍入或截断 文本的二进制双精度值,有关准确性的信息 FloatingDecimal 中的转换结果,以及任何 舍入完成,在此类中是必需的。

    • 对于下面的 HALF_DOWN、HALF_EVEN、HALF_UP 舍入规则: 在形成 float 或 double 的情况下,我们必须考虑 说明 FloatingDecimal 在二进制到十进制中所做的事情 转换。

      考虑到平局情况,FloatingDecimal 可能会四舍五入 值(当它低于时返回等于 tie 的十进制数字), 或在值高于它时将值“截断”到平局, 或在二进制值可以是时提供确切的十进制数字 在给定格式的情况下精确转换为其十进制表示 FloatingDecimal 的规则(因此我们有一个精确的小数 二进制值的表示)。

      • 如果双精度二进制值完全转换为十进制 值,则 DigitList 代码必须应用预期的舍入 规则。

      • 如果 FloatingDecimal 已经四舍五入十进制值, DigitList 不应在任何 以上三种舍入模式。

      • 如果 FloatingDecimal 已将十进制值截断为 结束 '5' 数字,DigitList 应将值四舍五入 以上三种舍入模式。

      只有当数字在 maximumDigits 索引时才需要考虑 正好是一组数字中的最后一个,否则有 该位置之后的剩余数字,我们不必考虑 FloatingDecimal 做了什么。

    • 其他舍入模式不受这些平局情况的影响。

    • 对于始终转换为精确数字的其他数字 (如 BigInteger、Long、...),传递的 alreadyRounded 布尔值 必须设置为 false,并且 allDecimalDigits 必须设置为 在上层 DigitList 调用堆栈中为 true,提供正确的状态 对于那些情况..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2013-08-21
      • 2016-04-28
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多