当我尝试这个时:
HashSet<Double> set = new HashSet<>();
Double d1 = new Double(0);
Double d2 = new Double(0);
Double d3 = new Double(-0);
set.add(d1);
System.out.println(set.contains(d2));
System.out.println(set.contains(d3));
输出符合我的预期:
true
true
但是当我尝试时:
HashSet<Double> set = new HashSet<>();
Double d1 = new Double(0.0);
Double d2 = new Double(0.0);
Double d3 = new Double(-0.0);
set.add(d1);
System.out.println(set.contains(d2));
System.out.println(set.contains(d3));
或
set.add(Double.valueOf(d1));
System.out.println(set.contains(Double.valueOf(d2)));
System.out.println(set.contains(Double.valueOf(d3)));
令我惊讶的是,输出结果为:
true
false
为什么会这样?如何使HashSet处理(0.0)和(-0.0)相同?
有没有比if(num == -0.0) num = 0.0;
更好的方式?
答案 0 :(得分:4)
Double
Double
解释了这一点。
如果d1表示+0.0而d2表示-0.0,反之亦然,则等于测试的值为false,即使+0.0 == - 0.0的值为true。
因此,从0.0
创建的Double
不与从-0.0
创建的0
相同。当您使用-0
和-0
时,情况也是如此,因为整数使用二进制补码,它没有负零概念。 0
与double
相同。另一方面,HashSet
是the docs,它确实识别负零值。
此行为已得到修复,因此无法0.0
对待-0.0
和self.userNameTextField.becomeFirstResponder()
self.passwordTextField.becomeFirstResponder()
。如果您想这样做,在添加或搜索之前,您需要手动将所有负零值转换为正零。
答案 1 :(得分:2)
-0.0
是double
值的文字,与0.0
不同。
-0
是应用于int
值0
的否定运算符,它仅提供int
值0
。
因此,new Double(-0)
相当于new Double(0)
,而new Double(-0.0)
和new Double(0.0)
实际上产生了两个不相等的Double
个对象。
有关为什么必须有两个不同的浮点零值,请参阅this question。
答案 2 :(得分:1)
正如维基百科(感谢)中所解释的,浮点的IEEE格式实际上由于各种原因支持负和正零。 https://en.wikipedia.org/wiki/Signed_zero
您在散列映射中发现0.0和-0.0不同的原因直接来自IEEE表示。 Double#hashCode方法使用浮点数的原始位来计算哈希码。由于0.0和-0.0甚至可能+0.0在位方面不同,因为一些数值计算显然需要这样,它们的位是不同的,因此是哈希码。