В Java 8 изменилась логика округления десятичных дробей в методе format классов
java.text.NumberFormat и java.text.DecimalFormat, когда
значение очень близко к границе округления, указанной в шаблоне форматирования. Изменение
проявляется в числах с неточным двоичным представлением.
Например, ближайшее двоичное представление числа 0,015, возможное на компьютере, равно 0,01499999999999999944488848768742172978818416595458984375. Если округлить это число до двух знаков после запятой, то в Java 8 ответ будет 0,01, так как 0,004999999.... меньше 0,005. В предыдущих версиях Java ответ - 0,02.
Это правило помечает методы format классов NumberFormat и
DecimalFormat с простым типом double или объектом java.lang.Double в первом параметре.
Пример использования методов format.
|
< span class="Code"> < span class= "JavaKeyword"> public static void < /span> main (< span class="JavaType"> String < /span> [] 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 + ") возвращает \"" + myStr + "\". Ожидается \"0.805\"."); nf.setMaximumFractionDigits(2); aDouble = 0.015d; myStr = nf.format(aDouble); System.out.println("format(" + aDouble + ") возвращает \"" + 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) возвращает \"" + myStr + "\". Ожидается \"55.5%\"."); } |
Если выполнить этот код в Java 7, будет выведена следующая информация:
< span class="Code"> формат (0.8055) возвращает "0.806". Ожидается "0.805".В Java 8 будет выведена следующая информация:
< span class="Code"> формат (0.8055) возвращает "0.805". Ожидается "0.805".Следует помнить об этом изменении, так как оно может повлиять на вывод данных программой. В отчете об ошибке JDK-7131459 содержится дополнительная информация и ссылки на связанные отчеты, включая отчеты для Java 8, в которых это обозначено как регрессионная ошибка.
Дополнительную информацию о затронутых классах можно найти в следующих ресурсах: