比较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反过来通过比较两个DoubledoubleToLongBits(...)来检查相等性,对于后者有一个保证

如果参数是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 Doubled1d2两个实例,当且仅当d1.doubleValue() == d2.doubleValue()的值为true时, d1.equals(d2)的值才为true。 但是,有两个例外:

  • 如果d1d2都表示Double.NaN ,那么即使Double.NaN==Double.NaN的值为false ,equals方法也会返回true

  • 如果d1表示+0.0d2表示-0.0 ,反之亦然,即使+0.0==-0.0的值为true ,相等测试的值为false

Interesting Posts