| benf.org : other : cfr : double comparison |
Thanks to Abe Crannaford for reporting this
As usual - this is (in retrospect, of course!) totally obvious, well documented, and shouldn't come as a surprise. The main reason I'm writing this up is because I was so surprised I'd got it wrong that I checked around the rest of the decompiler ecosystem, and it looks like (correct me if I'm wrong) every other java decompiler did too! (as of 2018/12), so it's worth mentioning!
Prior to 0.139, CFR incorrectly decompiled
public static void t1(double d) {
System.out.println(!(d < Double.NaN));
}
public static void t2(double d) {
System.out.println(d >= Double.NaN);
}
as
public static void t1(double d) {
System.out.println(d >= Double.NaN);
}
public static void t2(double d) {
System.out.println(d >= Double.NaN);
}
The above is wrong, because of NaN:
| d < NaN | false |
| d >= NaN | false |
| !(d >= NaN) | true |
public static void t1(double);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: dload_0
4: ldc2_w #4 // double NaNd
7: dcmpg
8: iflt 15
11: iconst_1
12: goto 16
15: iconst_0
16: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
19: return
public static void t2(double);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: dload_0
4: ldc2_w #4 // double NaNd
7: dcmpl
8: iflt 15
11: iconst_1
12: goto 16
15: iconst_0
16: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
19: return
Absolutely identical, apart from the crafty difference between dcmp*g* and dcmp*l*.
Fun!
java -jar cfr-0.139.jar cfr_tests\org\benf\cfr\tests\FloatEvalTest2.class
/*
* Decompiled with CFR 0.139.
*/
package org.benf.cfr.tests;
import java.io.PrintStream;
public class FloatEvalTest2 {
public static void t1(double d) {
System.out.println(!(d < Double.NaN));
}
public static void t2(double d) {
System.out.println(d >= Double.NaN);
}
public static /* varargs */ void main(String ... arrstring) {
FloatEvalTest2.t1(3.9);
FloatEvalTest2.t2(3.9);
}
}
| Last updated 01/2019 |