我读过这篇文章负和正零。
根据我的理解,以下代码应该给出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));
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我们对 0Integer和0 有不同的行为Float?
ysh*_*vit 17
Ints 和 floats 在 Java 中是完全不同的野兽。Ints 被编码为二进制补码,它有一个 0 值。浮点数使用IEEE 754(浮点数使用32 位变体,双精度数使用64位变体)。IEEE 754 有点复杂,但出于此答案的目的,您只需要知道它包含三个部分,其中第一个是符号位。这意味着对于任何浮动,都有一个积极和消极的变体¹。这包括 0,所以浮点数实际上有两个“零”值,+0 和 -0。
顺便说一句,int 使用的二进制补码并不是计算机科学中对整数进行编码的唯一方法。还有其他方法,比如ones'complement,但它们有一些怪癖——比如同时使用+0和-0作为不同的值。;-)
当您比较浮点基元(和双精度数)时,Java 将 +0 和 -0 视为相等。但是当您将它们装箱时,Java 将它们分开处理,如 中所述Float#equals。这让 equals 方法与它们的hashCode实现(以及compareTo)保持一致,它只使用浮点数的位(包括带符号的值)并将它们按原样推送到 int 中。
他们本可以为 equals/hashCode/compareTo 选择其他选项,但他们没有。我不确定那里的设计考虑是什么。但至少在一个方面,Float#equals总是会与 float 原语不同==:在原语中,NaN != NaN,但对于所有对象,o.equals(o)也必须为 true。这意味着,如果你有Float f = Float.NaN,那么f.equals(f)即使f.floatValue() != f.floatValue().
¹ NaN(非数字)值有一个符号位,但除了排序之外没有任何意义,Java 忽略它(即使是排序)。
有两个例外:
如果 f1 代表 +0.0f 而 f2 代表 -0.0f,反之亦然,则相等测试的值为false
还描述了原因:
此定义允许哈希表正常运行。
-0 和 0 将使用 Float 的第 31 位以不同方式表示:
第 31 位(由掩码 0x80000000 选择的位)表示浮点数的符号。
情况并非如此 Integer
| 归档时间: |
|
| 查看次数: |
411 次 |
| 最近记录: |