- (a - b) é a mesma coisa que (b - a)?

Segundo o que você aprendeu em matemática, é claro que - (a - b) é a mesma coisa que (b - a). Será?

Assim pensava o cara que fez uma otimização no JDK para economizar uma operação aritmética - sabe como é que é, cada bytecode e cada instrução conta, quando se trata de deixar seu programa mais rápido.

Só que há uma sutileza que impede usar essa identidade matemática

  • (a - b) == (b - a).

Essa sutileza aparece quando a e b são exatamente iguais.

Então, em Java, o primeiro lado dá o resultado -0.0, e o segundo lado dá o resultado +0.0. Nesse caso, como você deve saber, esses números são iguais quanto a usar “==”, mas não são a mesma coisa quanto eles são usados em algumas operações importantes.

Para perceber isso, note que em Java 1 / +0.0 é igual a +Infinity, e 1 / -0.0 é igual a -Infinity. O primeiro número (+Infinity) é obviamente muito diferente de -Infinity.

Mais detalhes em: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6796786

Note que muitos compiladores C e C++ também não fazem essa otimização “óbvia” - (a - b) == (b - a), justamente porque já encontraram essa sutileza antes.

Lembra, de alguma forma, o bug da busca binaria que o Joshua Bloch reportou, quando dava overflow:

Alias, trocando -(a-b) por (b-a) troca as situacoes que o overflow pode ocorrer. Também é algo a se pensar.

pensando melhor, nesse caso o overflow ocorre na mesma situacao, quando a é um positivo grande e b um negativo grande, e a subtracao de um e de outro estoura os 2bi no caso de int.

Não dá exceção?

eu pensei a mesma coisa quando eu li…

Essa identidade está considerando, pelo que entendi, que tanto a quanto b são do tipo double, certo? Se for isso mesmo, julgo que esse problema é velho conhecido.
É um bug “besta” mas muitas vezes atrapalha…

[EDIT]
Fiz o teste da igualdade e funcionou…
[/EDIT]

[EDIT 2]
Olhando melhor o bug entendi o problema. :slight_smile:
[/EDIT 2]

Hmm… há uma peculiaridade aqui. Olhando o bug (que está lá desde 2009), é quando a VM é chamada como -server que o mesmo ocorre. No modo client está tudo aparentemente certo. O código postado no bug realmente falha na condição específica.

Porém, um código mais simples não falha :expressionless:

Não dá exceção?[/quote]
Está trabalhando com ponto flutuante. Exceção ocorre apenas com inteiros.

System.out.println(20.0f/0.0f); System.out.println(20.0f/-0.0f);