java-为什么eval类给我一个从int到double的转换错误?

我试图制作一个采用字符串公式的方法,并通过以很小的间隔进行一次黎曼和求和来解决该公式的积分.我正在使用ScriptEngine和ScriptEngineManager类评估函数(使用eval()方法).由于某种原因,我收到此错误:

Exception in thread “main” java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
at sum.integral(sum.java:31)
at sum.main(sum.java:13)

import java.beans.Expression;

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

public class sum {

    //testing method
    public static void main(String[] args) throws ScriptException {

        double x = integral("5*x^2",0,5);
        System.out.println(x);

    }

    public static double integral(String function, double lower, double upper) throws ScriptException
    {
        double total = 0;

        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");

        //Solves function from upper to lower with a .001 interval, adding it to the total.
        for (double i = lower; i < upper; i+=.001)
        {
            //evaluates the interval
            engine.put("x",i);
            total += (double)engine.eval(function);
        }

        return total;
    }

}

解决方法:

Nashorn使用optimistic typing(从JDK 8u40开始),因此在不需要双精度时将使用整数.因此,您不能指望它返回Double.

同样,5 * x ^ 2在JavaScript中的意思是“ 5 x x或2”. **幂运算符在JavaScript语言的较新版本中定义,但Nashorn尚不支持它.

如果将JavaScript代码更改为5 * x * x,则可以使用,但是这样做会更安全:

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

编译常用代码

由于您是在循环中反复调用此函数,因此最佳实践是提前编译该函数.性能优化不是严格必要的,但因为引擎每次都必须编译您的函数(尽管它可能使用缓存来帮助您完成此工作).

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();

使用ES6语言功能

将来,当Nashorn确实支持**运算符时,如果要使用它,则可能需要打开ES6功能,如下所示:

import jdk.nashorn.api.scripting.NashornScriptEngineFactory;

NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine enjin = factory.getScriptEngine("--language=es6");

或像这样:

java -Dnashorn.args=--language=es6

*编辑以考虑到注释中指出的数学修正.

上一篇:c – 布尔的N区间规则(C)


下一篇:贪心中的邻项交换法