Я прочитал этот пост отрицательный и положительный нуль .
В моем понимании следующего кода должны дать true
и true
как выход.
Тем не менее, он дает false
и true
как выход.
Я сравнение отрицательного нуля с положительным нулем.
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));
}
}
Почему мы имеем различное поведение для 0 - х для Integer
и Float
?
Ints и поплавки довольно разные звери в Java. Ints кодируются как дополнения до двух , который имеет одну значение 0. Поплавки используют IEEE 754 (на 32-битный вариант для поплавков, а также 64-бит для двойников). IEEE 754 является довольно сложным, но для целей этого ответа, вам просто нужно знать , что она состоит из трех разделов, первый из которых является знаковым. Это означает , что для любого поплавка, есть положительные и отрицательные variant¹. Это включает в себя 0, так что поплавки на самом деле есть два «нулевых» значений, +0 и -0.
Как и в сторону, два в дополнение , что Интс использовать не единственный способ закодировать целые числа в информатике. Существуют и другие методы, такие как обратный код , но у них есть причуды - как имеющие как +0 и -0 , как различные значения. ;-)
При сравнении с плавающей точкой (примитивы и двойники), Java трактует +0 и -0 как равные. Но когда вы боксировать их, Java обрабатывает их по отдельности, как описано в Float#equals
. Это позволяет равно метод соответствовать их hashCode
реализациям (а также compareTo
), который просто использует биты поплавка ( в том числе, подписавших значений) и пихают них , как есть в междунар.
Они могли бы выбрать какой - то другой вариант для РАВНО / хэш - код / CompareTo, но они этого не сделали. Я не уверен , что конструктивные соображения были. Но , по крайней мере , одном отношении, Float#equals
всегда будет отличаться от поплавка примитива ==
: В примитивов NaN != NaN
, но для всех объектов, o.equals(o)
также должны быть правдой . Это означает , что если у вас Float f = Float.NaN
, то f.equals(f)
несмотря на то f.floatValue() != f.floatValue()
.
¹ NaN (не-число) значения имеют знаковый бит, но это не имеет никакого значения, кроме для заказа, и Java игнорирует его (даже при заказе).