Zmiana działania zaokrąglania w metodach formatujących NumberFormat i DecimalFormat

W języku Java 8 wprowadzono zmianę w działaniu zaokrąglania liczb dziesiętnych przy użyciu metody format w java.text.NumberFormat i java.text.DecimalFormat klasy, gdy wartość jest bardzo blisko krawata, siedząc dokładnie w pozycji zaokrąglania określonej we wzorcu formatowania. Zmiana ta wpływa na liczby o reprezentacji binarnej, która nie jest dokładna.

Na przykład najbliższym przybliżeniem binarnym liczby 0,015, które może uzyskać komputer, jest 0,01499999999999999944488848768742172978818416595458984375. Jeśli liczba ta zostanie zaokrąglona do dwóch cyfr, w języku Java 8 odpowiedzią będzie 0.01, ponieważ 0.004999999... jest mniejsze od 0.005. W poprzednich wersjach języka Java odpowiedzią jest wartość 0,02.

Ta reguła powoduje oznaczenie wywołań metod format klas NumberFormat i DecimalFormat, gdy są one wywoływane z wartością typu podstawowego double lub obiektem java.lang.Double jako pierwszym parametrem. W poniższym przykładzie przedstawiono sposób użycia metod 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 + ") zwraca \" "+ myStr +" \". Oczekiwano \"0.805\".");

nf.setMaximumFractionDigits(2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format (" + aDouble + ") zwraca \" "+ myStr +" \". Oczekiwano \"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) zwraca łańcuch \"" + myStr + " \". Oczekiwano \"55.5% \". ");

}

Jeśli ten kod zostanie wywołany w środowisku języka Java 7, zostaną wyświetlone następujące dane wyjściowe:

format(0.8055) zwraca "0.806". Oczekiwano "0.805".
format(0.015) zwraca "0.02". Oczekiwano "0.01".
format(0.5555) zwraca "55.6%". Oczekiwano "55.5%".

W środowisku języka Java 8 wyświetlane są następujące dane wyjściowe:

format(0.8055) zwraca "0.805". Oczekiwano "0.805".
format(0.015) zwraca "0.01". Oczekiwano "0.01".
format(0.5555) zwraca "55.5%". Oczekiwano "55.5%".

Należy pamiętać o tej zmianie działania, ponieważ może mieć wpływ na dane wyjściowe programu. Raport o błędzie JDK-7131459 zawiera więcej informacji i udostępnia kilka powiązanych raportów, w tym raporty o błędach dotyczących środowiska Java 8, w których pojawia się ta regresja.

Więcej informacji na temat klas, których dotyczy ta zmiana, zawierają następujące zasoby: