所以我最近开始喜欢语言kotlin。今天,在比较双打时,我遇到了不可避免的NaN
。
fun main(args: Array<String>) {
val nan = Double.NaN
println("1: " + (nan == nan))
println("2: " + (nan == (nan as Number)))
println("3: " + ((nan as Number) == nan))
}
N.B:( Double
是 Number
的子类型
运行上面的代码会产生:
1: false
2: true
3: true
我理解Java中的comparing NaN
会返回false
,所以对于所有表达式我都希望false
。
如何解释这种行为? 它背后的理由是什么?
答案 0 :(得分:10)
那是因为(2)和(3)被编译为装箱基元然后Double.equals
检查:在JVM上,原始{ {1}}无法与盒装版进行比较。
Double.equals
通过比较两个double
的{{3}}来检查相等性,而后者则保证
如果参数为NaN,则结果为
Double
。
因此,两个0x7ff8000000000000L
返回的位相等,此处忽略规则NaN
。
此外,正如 @miensol 所提到的,这种相等检查的另一个后果是:NaN != NaN
和+0
根据-0
检查是相等的而不是==
检查。
Java中的等效代码是:
equals
最后两行调用double nan = Double.NaN;
System.out.println("1: " + (nan == nan)) //false
System.out.println("2: " + ((Double) nan).equals(((Number) nan)))
System.out.println("3: " + ((Number) nan).equals(nan));
,比较Double.equals
。
答案 1 :(得分:8)
第一个比较等同于Java:
double left = Double.NaN;
double right = Double.NaN;
boolean result = left == right;
正如你可以read in this answer这是标准化和记录在案的行为。
第二个&amp;第三次比较相当于:
Double left = Double.valueOf(Double.NaN);
Number right = Double.valueOf(Double.NaN);
boolean result = left.equals(right);
请注意,在大多数情况下,对于
class Double
,d1
和d2
的两个实例, 当且仅当d1.equals(d2)
的值也为true时,d1.doubleValue() == d2.doubleValue()
的值才为真。但是,有两个 例外:
如果
d1
和d2
都代表Double.NaN
,那么等于 方法返回true
,即使Double.NaN==Double.NaN
具有值false
。如果
d1
代表+0.0
而d2
代表-0.0
,反之亦然, 等值测试的值为false
,即使+0.0==-0.0
具有 价值true
。