NumberFormat 和 DecimalFormat 格式化方法中的舍入行为更改

Java 8 引入了使用 format 方法对十进制数进行舍入的行为更改。 java.text.NumberFormat java.text.DecimalFormat 类,当该值与一个平差非常接近时,正好坐落在格式化模式中指定的舍入位置。 此更改将影响具有不准确的二进制数字表示法的数字。

例如,计算机可达到的 0.015 的最接近二进制近似值为 0.01499999999999999944488848768742172978818416595458984375。 如果将该数字向下舍入为两位小数, 那么在 Java 8 中,答案为 .01,因为 .004999999.... 小于 .005。 在先前版本的 Java 中,答案是 0.02。

当使用 double 原语或 java.lang.Double 对象作为第一个参数来调用 NumberFormatDecimalFormat format 方法时,此规则会标记对这些方法的调用。 以下示例显示了对这些 format 方法的使用。

public static void main(String[] args) {

java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
nf.setMaximumFractionDigits(3);
double aDouble;
String myStr;

aDouble = 0.8055d;
myStr = nf.format(aDouble);
System.out.println("format (" + aDouble + ") 返回 "+ myStr +"。 需要 "0.805\". ");

nf.setMaximumFractionDigits(2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format (" + aDouble + ") 返回 "+ myStr +"。 需要 "0.01\". ");


NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMinimumFractionDigits(1);
percent.setMaximumFractionDigits(1);
percent.setRoundingMode(RoundingMode.HALF_EVEN);
myStr = percent.format(0.5555);
System.out.println("format (0.5555) returns \"" + myStr + " \"。 需要 "55.5%". ");

}

如果您使用 Java 7 来调用该代码,那么将显示以下输出:

format(0.8055) 返回了“0.806”。 期望“0.805”。
format(0.015) 返回了“0.02”。 期望“0.01”。
format(0.5555) 返回了“55.6%”。 期望“55.5%”。

在 Java 8 中,将显示以下输出:

format(0.8055) 返回了“0.805”。 期望“0.805”。
format(0.015) 返回了“0.01”。 期望“0.01”。
format (0.5555) 返回了“55.5%”。 期望“55.5%”。

请注意该行为更改,因为它可能会影响程序输出。 JDK-7131459 错误报告提供了更多信息并显示了多个相关报告,包括针对 Java 8 的错误报告(将此错误报告为回归)。

有关受影响类的更多信息,请参阅以下资源: