Nan comparison in Javascript with javax.scriptEngine on JDK8

403 views Asked by At

According to IEEE 754 NaN equal comparison with any number should be false (both Java and JavaScript languages). But in the following code, using javax scriptEngine for JavaScript, a variable set to NaN compared with itself returns true.

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Main {

    public static void main(String[] args) throws ScriptException {
        final ScriptEngineManager mgr = new ScriptEngineManager();
        final ScriptEngine engine = mgr.getEngineByName("JavaScript");
        System.out.println("neq: " + engine.eval("a1 = NaN; a1!=a1;"));
        System.out.println("eq: " + engine.eval("a1 = NaN; a1==a1;"));
        System.out.println("nid: " + engine.eval("a1 = NaN; a1!==a1;"));
        System.out.println("id: " + engine.eval("a1 = NaN; a1===a1;"));
    }
}

Output :

neq: true
eq: true
nid: true
id: false

Using oracle JDK :

java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

My understanding is the 'eq' expression should return false.

Why is a1 == a1 True instead of False when a1 is NaN ?

2

There are 2 answers

2
Holger On

Whatever causes this behavior seems to be a side-effect of the assignment or, more specific, of the reassignment (within the same script). I modified your test case to

final ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
System.out.println("neq: " + engine.eval("a1 = NaN; a1!=a1;"));
System.out.println("eq: " + engine.eval("a1 = NaN; a1==a1;"));
System.out.println();
engine = mgr.getEngineByName("JavaScript");
System.out.println("eq: " + engine.eval("a1 = NaN; a1==a1;"));
System.out.println("neq: " + engine.eval("a1 = NaN; a1!=a1;"));
System.out.println();
engine = mgr.getEngineByName("JavaScript");
engine.eval("a1 = NaN;");
System.out.println("neq: " + engine.eval("a1!=a1;"));
System.out.println("eq: " + engine.eval("a1==a1;"));
System.out.println();
engine = mgr.getEngineByName("JavaScript");
engine.eval("a1 = NaN;");
System.out.println("eq: " + engine.eval("a1==a1;"));
System.out.println("neq: " + engine.eval("a1!=a1;"));

and got:

neq: true
eq: true

eq: false
neq: false

neq: false
eq: true

eq: true
neq: false

So when a1 does not get reassigned within an engine, it exhibits a consistent (not necessarily correct) behavior, while with the reassignment, the result is not just wrong but entirely inconsistent.

1
Thierry Pauwels On

If I add this piece of code

    engine.eval("a1 = NaN;");
    System.out.println("eq: " + engine.eval("a1==a1;"));
    System.out.println("neq: " + engine.eval("a1!=a1;"));
    System.out.println();
    engine.eval("a1 = NaN;a2 = NaN");
    System.out.println("eq: " + engine.eval("a1==a2;"));
    System.out.println("neq: " + engine.eval("a1!=a2;"));
    System.out.println();

it shows that even without reassignment the result is inconsistent. I get:

eq: true neq: false

eq: false neq: true