Apl*_*nus 12 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))
}
Run Code Online (Sandbox Code Playgroud)
NB :( Double 是子类型 )Number
运行上面的代码会产生:
1: false
2: true
3: true
Run Code Online (Sandbox Code Playgroud)
我理解与Java 相比,我会期望所有的表达式.NaNfalsefalse
如何解释这种行为?它背后的理由是什么?
hot*_*key 10
这是因为(2)和(3)被编译为装箱基元,然后Double.equals检查:在JVM上,基元double不能与盒装基元进行比较.
Double.equals反过来,通过比较doubleToLongBits(...)两个Doubles来检查相等性,而后者则保证这一点
如果参数是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));
Run Code Online (Sandbox Code Playgroud)
最后两行调用Double.equals,比较doubleToLongBits(...).
第一个比较等同于Java:
double left = Double.NaN;
double right = Double.NaN;
boolean result = left == right;
Run Code Online (Sandbox Code Playgroud)
第二次和第三次比较相当于:
Double left = Double.valueOf(Double.NaN);
Number right = Double.valueOf(Double.NaN);
boolean result = left.equals(right);
Run Code Online (Sandbox Code Playgroud)
哪个使用Double.equals:
请注意,在大多数情况下,对于两个实例
class Double,d1和d2,d1.equals(d2)当且仅当d1.doubleValue() == d2.doubleValue()值也为true时,值为true.但是,有两个例外:
如果
d1和d2两者都表示Double.NaN,那么true即使Double.NaN==Double.NaN有值 ,equals方法也会返回false.如果
d1代表+0.0whiled2表示-0.0,反之亦然,则等值测试具有该值false,即使+0.0==-0.0具有该值true.