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

Java 8 では、以下に対する format メソッドを使用した 10 進数の丸め動作の振る舞いの変更が導入されています。 java.text.NumberFormat および java.text.DecimalFormat 値がタイに非常に近いときに、フォーマット・パターンで指定された丸め位置に正確に座るクラス。 この変更は、端数のある 2 進数表現の数値に影響を与えます。

例えば、コンピューターがアクセスできる 0.015 に最も近い 2 進数の近似値は 0.01499999999999999944488848768742172978818416595458984375 です。 その数値を 2 桁に切り捨てると、Java 8 で 答えは .01 になり、.004999999....は .005 より小さい値ためです。 それ以前のバージョンの 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 + "¥". \"0.805\"を予期しています。");

nf.setMaximumFractionDigits(2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format (" + aDouble + ") returns ¥ "" + 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 を使用してこのコードを呼び出すと、以下の出力が表示されます。

フォーマット(0.8055) は「0.806」を返します。 「0.805」が予期されています。
フォーマット (0.015) は「0.02」を返します。 「0.01」が予期されています。
フォーマット (0.5555) は「55.6%」を返します。 「55.5%」が予期されています。

Java 8 では、以下の出力が表示されます。

フォーマット (0.8055) は「0.805」を返します。 「0.805」が予期されています。
フォーマット (0.015) は「0.01」を返します。 「0.01」が予期されています。
フォーマット (0.5555) は「55.5%」を返します。 「55.5%」が予期されています。

この振る舞いの変更は、プログラムの出力に影響を与える可能性があるため、認識しておいてください。 JDK-7131459 バグ・レポートには、詳細といくつかの関連レポート (これを回帰として報告する Java 8 に対するバグ・レポートを含む) が記載されています。

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