在 Kotlin 中比较 NaN
Comparing NaN in 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
我明白 comparing 和 NaN
在 Java returns false
中,所以我希望所有表达式都是 false
。
如何解释这种行为?
背后的原理是什么?
那是因为 (2) 和 (3) 被编译为装箱原语,然后 Double.equals
检查:开JVM,原始 double
无法与盒装相比。
两个 Double
中的 Double.equals
, in turn, checks equality by comparing doubleToLongBits(...)
,而对于后者,可以保证
If the argument is NaN, the result is 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;
尽你所能 read in this answer 这是标准化和记录在案的行为。
第二次和第三次比较相当于:
Double left = Double.valueOf(Double.NaN);
Number right = Double.valueOf(Double.NaN);
boolean result = left.equals(right);
其中使用 Double.equals:
Note that in most cases, for two instances of class Double
, d1
and d2
,
the value of d1.equals(d2)
is true if and only if d1.doubleValue() ==
d2.doubleValue()
also has the value true. However, there are two
exceptions:
If d1
and d2
both represent Double.NaN
, then the equals
method returns true
, even though Double.NaN==Double.NaN
has the value
false
.
If d1
represents +0.0
while d2
represents -0.0
, or vice versa,
the equal test has the value false
, even though +0.0==-0.0
has the
value true
.
所以我最近开始喜欢上了 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
我明白 comparing 和 NaN
在 Java returns false
中,所以我希望所有表达式都是 false
。
如何解释这种行为? 背后的原理是什么?
那是因为 (2) 和 (3) 被编译为装箱原语,然后 Double.equals
检查:开JVM,原始 double
无法与盒装相比。
Double
中的 Double.equals
, in turn, checks equality by comparing doubleToLongBits(...)
,而对于后者,可以保证
If the argument is NaN, the result is
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;
尽你所能 read in this answer 这是标准化和记录在案的行为。
第二次和第三次比较相当于:
Double left = Double.valueOf(Double.NaN);
Number right = Double.valueOf(Double.NaN);
boolean result = left.equals(right);
其中使用 Double.equals:
Note that in most cases, for two instances of
class Double
,d1
andd2
, the value ofd1.equals(d2)
is true if and only ifd1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If
d1
andd2
both representDouble.NaN
, then the equals method returnstrue
, even thoughDouble.NaN==Double.NaN
has the valuefalse
.If
d1
represents+0.0
whiled2
represents-0.0
, or vice versa, the equal test has the valuefalse
, even though+0.0==-0.0
has the valuetrue
.