Why is the eval class giving me a casting error from int to double?

前端 未结 2 679
不知归路
不知归路 2021-01-15 13:51

I am trying to make a method that takes a string formula, and solves the integral of that formula by doing a Riemann\'s sum with very small intervals. I am using the ScriptE

2条回答
  •  迷失自我
    2021-01-15 14:18

    Nashorn uses optimistic typing (since JDK 8u40), so it will using integers when doubles are not needed. Thus, you cannot count on it returning a Double.

    Also, 5*x^2 means "five times x xor two" in JavaScript. The ** exponentiation operator is defined in newer versions of the JavaScript language, but Nashorn doesn't support it yet.

    If you change your JavaScript code to 5*x*x it will work, but it would be safer to do:

    total += 0.001 * ((Number)engine.eval(function)).doubleValue();
    

    Compiling Frequently Used Code

    Since you call this function repeatedly in a loop, a best practice is to compile the function in advance. This performance optimization is not strictly necessary, but as it is the engine has to compile your function every time (although it may use a cache to help with that).

    import javax.script.Compilable;
    import javax.script.CompiledScript;
    import javax.script.Invocable;
    import javax.script.ScriptContext;
    
    CompiledScript compiledScript = ((Compilable)engine)
        .compile("function func(x) { return " + function + "}");
    compiledScript.eval(compiledScript.getEngine()
        .getBindings(ScriptContext.ENGINE_SCOPE));
    
    Invocable funcEngine = (Invocable) compiledScript.getEngine();
    
    // . . .
    
    total += 0.001 * ((Number)funcEngine.invokeFunction("func", i)).doubleValue();
    

    Using ES6 Language Features

    In the future, when Nashorn does support the ** operator, if you want to use it you may need to turn on ES6 features like this:

    import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
    
    NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
    ScriptEngine enjin = factory.getScriptEngine("--language=es6");
    

    Or like this:

    java -Dnashorn.args=--language=es6
    

    * Edited to account for the mathematical fix pointed out in the comments.

提交回复
热议问题