为什么eval类给我一个从int到double的转换错误? [英] Why is the eval class giving me a casting error from int to double?

查看:169
本文介绍了为什么eval类给我一个从int到double的转换错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 ScriptEngine and ScriptEngineManager classes to evaluate the function (with the eval() method). For some reason, I am getting this error:

线程"main"中的异常java.lang.ClassCastException:无法将java.lang.Integer强制转换为java.lang.Double 在sum.integral(sum.java:31) 在sum.main(sum.java:13)

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使用乐观打字(因为 JDK 8u40 ),因此在不需要双精度时会使用整数.因此,您不能指望它返回Double.

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.

此外,5*x^2在JavaScript中的含义是"5 x x 2". **幂运算符在JavaScript语言的较新版本中定义,但Nashorn尚不支持它.

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.

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

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

编译常用代码

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

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

使用ES6语言功能

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

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

或者像这样:

java -Dnashorn.args=--language=es6

*编辑为说明注释中指出的数学修正.

这篇关于为什么eval类给我一个从int到double的转换错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆