Java 8 では、java.text.NumberFormat クラスと java.text.DecimalFormat クラスで format メソッドを使用して 小数を丸めるときに、値が、丸めの基準となる中間値 (フォーマット設定パターンによって指定された丸めの位置とまったく等しい) に非常に近い場合の振る舞いが変更されました。 この変更は、端数のある 2 進数表現の数値に影響を与えます。
例えば、コンピューターがアクセスできる 0.015 に最も近い 2 進数の近似値は 0.01499999999999999944488848768742172978818416595458984375 です。 その数値を 2 桁に切り捨てると、Java 8 で 答えは .01 になり、.004999999....は .005 より小さい値ためです。 それ以前のバージョンの Java では、答えは 0.02 になります。
この規則により、NumberFormat と
DecimalFormat の 各 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 を使用してこのコードを呼び出すと、以下の出力が表示されます。
フォーマット(0.8055) は「0.806」を返します。 「0.805」が予期されています。Java 8 では、以下の出力が表示されます。
フォーマット (0.8055) は「0.805」を返します。 「0.805」が予期されています。この振る舞いの変更は、プログラムの出力に影響を与える可能性があるため、認識しておいてください。 JDK-7131459 バグ・レポートには、詳細といくつかの関連レポート (これを回帰として報告する Java 8 に対するバグ・レポートを含む) が記載されています。
影響を受けるクラスについて詳しくは、以下のリソースを参照してください。