比较Kotlin中的NaN

时间:2016-06-17 14:28:20

标签: floating-point nan kotlin

所以我最近开始喜欢语言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

如何解释这种行为? 它背后的理由是什么?

2 个答案:

答案 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);

使用Double.equals

  

请注意,在大多数情况下,对于class Doubled1d2的两个实例,   当且仅当d1.equals(d2)的值也为true时,d1.doubleValue() == d2.doubleValue()的值才为真。但是,有两个   例外:

     
      
  • 如果d1d2都代表Double.NaN,那么等于   方法返回true,即使Double.NaN==Double.NaN具有值   false

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

  •