当前位置: 首页 > 面试题库 >

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

韩耘豪
2023-03-14
问题内容

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

线程“主”中的异常java.lang.ClassCastException:无法将位于sum.main(sum.java:13)处sum.integral(sum.java:31)的java.lang.Integer强制转换为java.lang.Double。

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。

同样,5*x^2在JavaScript中的意思是“五倍x两倍”。该**幂运算符是JavaScript语言的较新版本定义,但犀牛不支持它。

如果将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

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



 类似资料:
  • 问题内容: 您可以将int隐式转换为double: 您可以将int显式转换为double: 您可以将double显式转换为int: 为什么不能将一个double隐式转换为int? : 问题答案: 的范围比宽。这就是为什么您需要显式强制转换。由于相同的原因,您不能隐式地从转换为:

  • 问题内容: 我的朋友正在尝试将某种计算作为上课的一项任务,但他遇到了一些麻烦…希望您能为他提供帮助。 问题在于他从用户那里得到了一个int的输入(这必须是任务的一部分)。他正在尝试在下面的代码中将其转换为double,但这是行不通的。无论如何结果都是int。 如果您需要更多说明,我会请他提供。提前致谢! 问题答案: 您必须将一个(或两个)参数传递给除法运算符: 由于您两次执行相同的计算,因此建议您

  • 我得到这个错误的一个小箭头指向十进制整数。允许小数吗?我要写些什么才能让小数被接受?这是我的代码:

  • 前面讲到,C++可以在必要的时候自动将int转换为double,因为这种转换没有损失信息。反之,double转换为int则需圆整。C++不会自动执行这种转换,这是为了让程序员意识到,这样做会损失小数部分。 将浮点数转换为整型数的最简单方法是用类型转换(typecast)。之所以称之为类型转换,是因为它允许你将某种类型的一个值“回炉”成另一类型,这里“回炉”指的是再造或重塑,而非报废。 类型转换的语

  • 问题内容: 在日食中显示错误。这是总和是122字节范围内的范围。所以为什么我在这里出现此错误。 提前致谢… 问题答案: 当您对字节执行数学运算时,Java会对字节进行扩展(自动类型提升)到字节(隐式转换)以对这种情况进行整数处理。所以当你表演 由于t1 + t2的结果比字节宽,因此您需要将其下转换为字节。 消除编译错误。 有关更多信息,请阅读 JLS 5.1.2