NumberFormat および DecimalFormat の各 format メソッドでの丸めの振る舞いの変更

Java 8 では、java.text.NumberFormat クラスと java.text.DecimalFormat クラスで format メソッドを使用して 小数を丸めるときに、値が、丸めの基準となる中間値 (フォーマット設定パターンによって指定された丸めの位置とまったく等しい) に非常に近い場合の振る舞いが変更されました。この変更は、端数のある 2 進数表現の数値に影響を与えます。

例えば、コンピューターがアクセスできる 0.015 に最も近い 2 進数の近似値は 0.01499999999999999944488848768742172978818416595458984375 です。この数値を 2 桁に丸める場合、.004999999.... は .005 より小さいため、Java 8 での答えは .01 になります。それ以前のバージョンの Java では、答えは 0.02 になります。

この規則により、NumberFormatDecimalFormat の 各 format メソッドが、double プリミティブまたは java.lang.Double オブジェクトを最初のパラメーターとして使用して呼び出された場合に、それらのメソッドにフラグを立てます。 以下の例では、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 に対するバグ・レポートを含め、複数の関連レポートが示されています。

影響を受けるクラスについて詳しくは、以下のリソースを参照してください。