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 |