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

Java 8 引入了如下小数舍入行为更改:当值非常接近时使用 java.text.NumberFormatjava.text.DecimalFormat 类上的 format 方法,从而正好符合格式化模式中指定的舍入位置。此更改将影响具有不准确的二进制数字表示法的数字。

例如,计算机可达到的 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 + ") returns \"" + myStr + "\". Expecting \"0.805\".");

nf.setMaximumFractionDigits(2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format(" + aDouble + ") returns \"" + myStr + "\". Expecting \"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 + "\". Expecting \"55.5%\".");

}

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

format(0.8055) returns "0.806". Expecting "0.805".
format(0.015) returns "0.02". Expecting "0.01".
format(0.5555) returns "55.6%". Expecting "55.5%".

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

format(0.8055) returns "0.805". Expecting "0.805".
format(0.015) returns "0.01". Expecting "0.01".
format(0.5555) returns "55.5%". Expecting "55.5%".

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

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