由边缘情况的DecimalFormat / RoundingMode.Down功能混淆

时间:2017-10-13 19:36:17

标签: java floating-point decimalformat

基于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?

1 个答案:

答案 0 :(得分:1)

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

查看课程shouldRoundUp(...)中方法java.text.DigitList的{​​{3}}中的评论:

  

避免在转换时出现错误的双舍入或截断   文本的二进制double值,有关正确性的信息   FloatingDecimal中的转换结果,以及任何   在这堂课中需要完成四舍五入。

     
      
  • 对于HALF_DOWN,HALF_EVEN,HALF_UP舍入规则如下:   在形成浮动或双重的情况下,我们必须考虑到   将FloatingDecimal在二进制文件中执行的操作转换为十进制   转换。

         

    考虑到绑定案例,FloatingDecimal可以对其进行舍入   value(当它低于时返回十进制数字等于tie),   或"截断"当价值高于它时领带的价值,   或者在二进制值可以时提供精确的十进制数字   在给定格式化时精确转换为十进制表示   FloatingDecimal的规则(因此我们有一个确切的小数   表示二进制值)。

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

    •   
    • 如果FloatingDecimal已经向上舍入小数值,   DigitList不应该在任何一个中再次舍入该值   上面的三种舍入模式。

    •   
    • 如果FloatingDecimal将十进制值截断为   结尾' 5'数字,DigitList应该向上舍入值   以上所有三种舍入模式。

    •   
         

    仅当maximumDigits指数处的数字时才需要考虑   正是数字集中的最后一个,否则就是   该位置后的剩余数字,我们不必考虑   FloatingDecimal做了什么。

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

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

  •