+0和-0显示Java-8中int和float的不同行为

时间:2019-12-11 06:28:31

标签: java java-8

我已经看过这篇文章negative and positive zero

据我了解,以下代码应产生truetrue作为输出。

但是,它提供falsetrue作为输出。

我正在将负零与正零进行比较。

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));
      }
  }

为什么对于IntegerFloat数据类型,零的行为不同?

3 个答案:

答案 0 :(得分:15)

整数和浮点数在Java中是完全不同的野兽。整数编码为two's complement,具有单个0值。浮点数使用IEEE 75432-bit variant代表浮点数,64-bit代表双打)。 IEEE 754有点复杂,但是出于这个答案的目的,您只需要知道它包含三个部分,第一个部分是符号位。这意味着对于任何浮动货币,都有正面和负面的变化¹。其中包括0,因此浮点数实际上有两个“零”值,即+0和-0。

顺便说一句,int使用的二进制补码并不是计算机科学中编码整数的唯一方法。还有其他方法,例如ones' complement,但它们也有一些怪异之处,例如+0和-0都是不同的值。 ;-)

比较浮点图元(和双精度)时,Java将+0和-0视为相等。但是,当您将它们装箱时,Java会分别对待它们,如Float#equals中所述。这使equals方法与其hashCode实现(以及compareTo)保持一致,该实现只使用float的位(包括带符号的值)并将它们按原样推入int。

他们可以为equals / hashCode / compareTo选择其他选项,但没有。我不确定当时的设计考虑因素是什么。但是至少在某一方面,Float#equals总是会与浮点图元的==不同:在图元中,NaN != NaN,但是for all objects, o.equals(o) must also be true。这意味着如果您拥有Float f = Float.NaN,那么即使f.equals(f)也有f.floatValue() != f.floatValue()


¹NaN(非数字)值具有符号位,但是除了用于排序外没有其他含义,Java会忽略它(甚至用于排序)。

答案 1 :(得分:10)

这是Float equals exception

之一
  

有两个例外:

     

如果f1代表+ 0.0f,而f2代表-0.0f ,反之亦然,相等测试的值为 false

原因也被描述:

  

此定义允许哈希表正常运行。

-0和0将使用Float的第31位来表示不同:

  

位31(由掩码0x80000000选择的位)表示浮点数的符号。

Integer中不是这种情况

答案 2 :(得分:5)

对于整数,整数-0和0之间没有区别,因为它使用Twos compliment表示形式。因此,您的整数示例ii1完全相同。

对于浮点数,有-0表示形式,其值等于0,但位表示形式不同。因此,新的Float(0f)和新的Float(-0f)将具有不同的表示形式。

您可以看到位表示形式的差异。

System.out.println(Float.floatToIntBits(-0f) + ", " + Float.floatToIntBits(0f));
  

-2147483648,0

如果您不使用f来声明-0f,那么它将被视为整数,并且您不会在输出中看到任何差异。