A mudança de comportamento no arredondamento em métodos de formato NumberFormat e DecimalFormat

O Java 8 introduz uma mudança de comportamento no comportamento de arredondamento de números decimais usando o método format no java.text.NumberFormat e o java.text.DecimalFormat quando o valor estiver muito próximo de um empate, sentado exatamente na posição de arredondamento especificada no padrão de formatação. A mudança afeta números com uma representação numérica binária que não é exata.

Por exemplo, a maior aproximação binária de 0,015 que um computador pode atingir é 0,01499999999999999944488848768742172978818416595458984375. Se você arredondar esse número para dois dígitos, em Java 8 a resposta será .01 porque .004999999.... é menor que 0,005. Em versões anteriores do Java, a resposta é 0,02.

Essa regra sinaliza chamadas aos métodos NumberFormat e DecimalFormat format quando eles são chamados com uma primitiva double ou um objeto java.lang.Double como o primeiro parâmetro O exemplo a seguir mostra o uso dos métodos 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 + ") retorna \" "+ myStr +" \". Esperando \"0.805\".");

nf.setMaximumFractionDigits (2);
aDouble = 0.015d;
myStr = nf.format(aDouble);
System.out.println("format (" + aDouble + ") retorna \" "+ myStr +" \". Esperando \"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) retorna \"" + myStr + " \". Esperando \"55.5% \". ");

}

Se você chamar esse código usando o Java 7, a saída a seguir será exibida:

format(0.8055) retorna "0.806". Esperando "0.805".
format(0.015) retorna "0.02". Esperando "0.01".
format(0.5555) retorna "55.6%". Esperando "55.5%".

No Java 8, a saída a seguir é exibida:

format(0.8055) retorna "0.805". Esperando "0.805".
format(0.015) retorna "0.01". Esperando "0.01".
format(0.5555) retorna "55.5%". Esperando "55.5%".

Esteja ciente dessa mudança de comportamento, porque isso pode afetar sua saída de programa. O Relatório de erro JDK-7131459 fornece mais informações e mostra vários relatórios relacionados, incluindo relatórios de erro com relação ao 8 que relatam isso como uma regressão.

Para obter informações adicionais sobre as classes afetadas, veja os recursos a seguir: