比较Kotlin中的NaN
所以我最近开始热爱语言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)) }
注意:( Double
是 Number
一个子类型 )
运行上面的代码产生:
1: false 2: true 3: true
我明白,与Java中的NaN
进行比较会返回false
,所以我希望所有表达式都是false
。
这个行为如何解释? 它背后的理由是什么?
这是因为(2)和(3)被编译为Double.equals
原语,然后Double.equals
检查:在JVM上,原始double
不能与装箱的比较。
Double.equals
反过来通过比较两个Double
的doubleToLongBits(...)
来检查相等性,对于后者有一个保证
如果参数是NaN,结果是
0x7ff8000000000000L
。
所以,返回两个NaN
的位相等,这里忽略规则NaN != NaN
。
另外,正如@miensol所提到的,还有另一个这种相等性检查的结果:根据==
检查+0
和-0
是相等的,而不是equals
检查。
Java中的等价代码将是:
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
,比较doubleToLongBits(...)
。
第一个比较相当于Java的:
double left = Double.NaN; double right = Double.NaN; boolean result = left == right;
正如你可以阅读这个答案这是标准化和记录的行为。
第二和第三个比较相当于:
Double left = Double.valueOf(Double.NaN); Number right = Double.valueOf(Double.NaN); boolean result = left.equals(right);
其中使用Double.equals :
请注意,在大多数情况下,对于
class Double
,d1
和d2
两个实例,当且仅当d1.doubleValue() == d2.doubleValue()
的值为true时,d1.equals(d2)
的值才为true。 但是,有两个例外:
如果
d1
和d2
都表示Double.NaN
,那么即使Double.NaN==Double.NaN
的值为false
,equals方法也会返回true
。如果
d1
表示+0.0
而d2
表示-0.0
,反之亦然,即使+0.0==-0.0
的值为true
,相等测试的值为false
。