简体   繁体   English

对于边缘情况,由DecimalFormat / RoundingMode.Down功能混淆

[英]Confused by DecimalFormat/RoundingMode.Down functionality for edge cases

Based on this stackoverflow post , I would expect the following to print out 0.59 and not 0.60. 基于这个stackoverflow帖子 ,我希望以下内容打印出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
    }
}

The closest floating point representation of 0.60 is 0.59999999999999997779553950749686919152736663818359375, which is below 0.6. 0.60的最接近浮点表示形式是0.59999999999999997779553950749686919152736663818359375,该数值低于0.6。 With DecimalFormat set to RoundingMode.DOWN in Java 8, why isn't this rounded down to 0.59? 在Java 8中将DecimalFormat设置为RoundingMode.DOWN时,为什么不将其四舍五入为0.59?

Because the formatting code is aware of the precision of a double . 因为格式化代码知道double的精度。

See comment in source code of method shouldRoundUp(...) in class java.text.DigitList : 请参见类java.text.DigitList中方法shouldRoundUp(...) 源代码中的注释:

To avoid erroneous double-rounding or truncation when converting a binary double value to text, information about the exactness of the conversion result in FloatingDecimal, as well as any rounding done, is needed in this class. 为了避免在将二进制双精度值转换为文本时错误的双精度舍入或截断,此类中需要有关FloatingDecimal中转换结果的准确性以及进行的所有舍入的信息。

  • For the HALF_DOWN, HALF_EVEN, HALF_UP rounding rules below: In the case of formating float or double, We must take into account what FloatingDecimal has done in the binary to decimal conversion. 对于下面的HALF_DOWN,HALF_EVEN和HALF_UP舍入规则:在格式化float或double的情况下,我们必须考虑到FloatingDecimal在二进制到十进制转换中所做的事情。

    Considering the tie cases, FloatingDecimal may round-up the value (returning decimal digits equal to tie when it is below), or "truncate" the value to the tie while value is above it, or provide the exact decimal digits when the binary value can be converted exactly to its decimal representation given formating rules of FloatingDecimal ( we have thus an exact decimal representation of the binary value). 考虑到平局的情况,FloatingDecimal可以对值进行四舍五入(当低于此值时返回等于tie的十进制数字),或者当该值在其之上时将值“截断”为tie,或者当二进制值时提供准确的十进制数字在给定FloatingDecimal格式规则的情况下,可以将其精确地转换为其十进制表示形式(因此,我们具有二进制值的精确十进制表示形式)。

    • If the double binary value was converted exactly as a decimal value, then DigitList code must apply the expected rounding rule. 如果将双二进制值完全转换为十进制值,则DigitList代码必须应用期望的舍入规则。

    • If FloatingDecimal already rounded up the decimal value, DigitList should neither round up the value again in any of the three rounding modes above. 如果FloatingDecimal已经四舍五入到十进制值,则DigitList都不应该在上述三种舍入模式中的任何一种下再次四舍五入该值。

    • If FloatingDecimal has truncated the decimal value to an ending '5' digit, DigitList should round up the value in all of the three rounding modes above. 如果FloatingDecimal已将十进制值截断为结尾的'5'数字,则DigitList应该在上述所有三种舍入模式中将其舍入。

    This has to be considered only if digit at maximumDigits index is exactly the last one in the set of digits, otherwise there are remaining digits after that position and we don't have to consider what FloatingDecimal did. 仅当maximumDigits索引处的数字恰好是数字集中的最后一个数字时,才必须考虑这一点,否则该位置之后将剩下剩余的数字,我们不必考虑FloatingDecimal做了什么。

  • Other rounding modes are not impacted by these tie cases. 其他舍入模式不受这些平局情况的影响。

  • For other numbers that are always converted to exact digits (like BigInteger, Long, ...), the passed alreadyRounded boolean have to be set to false, and allDecimalDigits has to be set to true in the upper DigitList call stack, providing the right state for those situations.. 对于总是转换为精确数字的其他数字(例如BigInteger,Long等),必须将传递的hasRounded布尔值设置为false,并且必须在上方DigitList调用堆栈中将allDecimalDigits设置为true,以提供正确的陈述这些情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM