Eu li este post com zero negativo e positivo .
Para meu entendimento, o código a seguir deve dar true
e true
como saída.
No entanto, está dando false
e true
como saída.
Estou comparando zero negativo com um zero positivo.
public class Test {
public static void main(String[] args) {
float f = 0;
float f2 = -f;
Float F = new Float(f);
Float F1 = new Float(f2);
System.out.println(F1.equals(F));
int i = 0;
int i2 = -i;
Integer I = new Integer(i);
Integer I1 = new Integer(i2);
System.out.println(I1.equals(I));
}
}
Por que temos um comportamento diferente para zeros para Integer
e Float
?
i
ei2
são exatamente iguais. Então, quando você cria novosInteger
s, ambos envolvem exatamente o mesmo valor.I1.equals(I)
será verdade.int i = Integer.MIN_VALUE, i2 = -i;
...new
os tipos de wrapper aqui. Basta usar, por exemplo,Integer i = 0, i2 = -i; System.out.println(i.equals(i2)); Float f1 = 0f, f2 = -f1; System.out.println(f1.equals(f2));
Respostas:
Ints e floats são bestas bem diferentes em Java. Ints são codificados como complemento de dois , que possui um único valor 0. Os flutuadores usam IEEE 754 (a variante de 32 bits para flutuadores e 64 bits para duplos). O IEEE 754 é um pouco complexo, mas, para o propósito desta resposta, você só precisa saber que ele possui três seções, a primeira das quais é um sinal. Isso significa que para qualquer flutuação, há uma variante positiva e negativa¹. Isso inclui 0, então os flutuadores realmente têm dois valores "zero", +0 e -0.
Como um aparte, o complemento dos dois que os ints usam não é a única maneira de codificar números inteiros na ciência da computação. Existem outros métodos, como o complemento de alguns , mas eles têm peculiaridades - como ter ambos os valores +0 e -0 como valores distintos. ;-)
Quando você compara primitivas flutuantes (e duplas), Java trata +0 e -0 como iguais. Mas quando você caixa-los, Java trata-los separadamente, como descrito em
Float#equals
. Isso permite que o método equals seja consistente com suahashCode
implementação (e tambémcompareTo
), que apenas usa os bits do float (incluindo esse valor assinado) e os coloca como estão em um int.Eles poderiam ter escolhido outra opção para equals / hashCode / compareTo, mas não o fizeram. Não sei ao certo quais eram as considerações de design. Mas, pelo menos em um aspecto,
Float#equals
sempre divergiria dos primitivos do float==
: nos primitivosNaN != NaN
, mas para todos os objetos,o.equals(o)
também deve ser verdade . Isso significa que se você tivesseFloat f = Float.NaN
,f.equals(f)
mesmo assimf.floatValue() != f.floatValue()
.Values Os valores de NaN (não um número) têm um bit de sinal, mas não têm outro significado além de para pedidos e o Java os ignora (mesmo para pedidos).
fonte
Este é um dos exceção de flutuação igual
O porquê também é descrito:
-0 e 0 serão representados de maneira diferente usando o bit 31 do Float:
Este não é o caso em
Integer
fonte
Para os números inteiros, não há distinção entre -0 e 0 para números inteiros porque ele usa a representação de complemento de dois . Portanto, o seu exemplo inteiro
i
ei1
são exatamente os mesmos.Para os carros alegóricos, existe uma representação -0 e seu valor é equivalente a 0, mas a representação de bit é diferente. Portanto, o novo Float (0f) e o novo Float (-0f) teriam representações diferentes.
Você pode ver a diferença nas representações de bits.
E se você deixar
f
de declarar o-0f
, ele será tratado como um número inteiro e você não verá nenhuma diferença na saída.fonte
0.0f == -0.0f
. Portanto, o comportamento diferente é apenasjava.lang.Float
.float
, que está de acordo com o IEEE754 a esse respeito e ojava.lang.Float
que não. Portanto, apenas a diferença na representação de bits não é suficiente para explicar isso.