将数学字符串转换为整数

5

有没有简单的方法将类似于“5*4”的字符串转换为20?


1
这个问题已经在https://dev59.com/LXE85IYBdhLWcg3wzWzM中有重复了。 - Adeel
2
@Adeel:不是的... C# 和 Java 是不同的编程语言,拥有不同的库和程序。 - animuson
1
@Adeel - 绝对不是,另一个问题要求使用C#解决方案。 - Andreas Dolk
11个回答

6
最简单的方法是使用JRE 6标准API中提供的Rhino JavaScript引擎编辑:根据评论,如果字符串由用户提供,则可能存在安全漏洞。请务必除了数字、括号和数学运算符之外,过滤掉所有内容。

3
是的...但JavaScript引擎除此之外还有很多其他功能。如果在某些上下文中暴露Rhino评估器,可能会引入安全问题。 - Stephen C
3
这种事情总是让我想起SQL注入攻击。如果这些字符串来自程序外部(比如用户、文件、套接字等),为了确保它们不会成为潜在的安全风险,你可能需要对它们进行解析。好吧,也许不用那么严格 - 你可能只需要使用正则表达式检查一下其合法性就可以了。而且Javascript没有标准文件操作等功能,所以你也许是安全的。但是,这仍然让我感到不安。 - user180247
哦,我在评论之前应该刷新页面的。算了。 - user180247

3

4
值得指出的是,它并不是免费的(无论从哪个意义上说)。 - Simon Nickerson
1
Artem,你认真的吗?“This”是一个可怕的链接描述符,而且回滚我的编辑是完全无知的。 - animuson

3
我不知道哪些是最好的,但有一些“数学表达式求值器”包。
请查看Java Math Expression Evaluator(包括一个文件源代码)。 网站上的使用示例:

java -cp meval.jar com.primalworld.math.MathEvaluator -cos(0)*(1+2)
java -cp meval.jar com.primalworld.math.MathEvaluator .05*200+3.01


由于我正在开发版本5,所以这个对我来说是最好的选择。 - George

2

我已经进行了一些谷歌搜索,并找到了一个 这里。虽然不完全符合你的需求,但或许会有所帮助。

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

public class ScriptDemo {

    public static void main(String[] args) {

        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");

        engine.put("a", 1);
        engine.put("b", 2);

        try {
            String expression = "(a + b) > 2";
            Object result = engine.eval(expression);
            System.out.println(expression+" ? "+result);
        } catch(ScriptException se) {
            se.printStackTrace();
        }
    }
}

2
听起来你应该看看JEXL(Java表达式语言)。
它非常容易使用;例如,解决你的问题的方法是:
  public static void main(String[] args) {
    long a = 5;
    long b = 4;
    String theExpression = "a * b";
    JexlEngine jexl = new JexlEngine();
    Expression e = jexl.createExpression(theExpression);
    JexlContext context = new MapContext();
    context.set("a", a);
    context.set("b", b);
    Long result = (Long) e.evaluate(context);
    System.out.println("The answer : " + result);
  }

如果直接读取字符串,您也可以使用以下方法:
 public static void main(String[] args) {
   JexlEngine jexl = new JexlEngine();
   Expression e = jexl.createExpression("5 * 4");
   Integer result = (Integer) e.evaluate(null);
   System.out.println("The answer : " + result);
 }

2

1

你也可以使用BeanShell
它实际上是一个Java源代码解释器,但最近我用它来评估一些包含变量的表达式(只有eval方法使用了BeanShell,其余部分是为了准备输出):

import bsh.EvalError;
import bsh.Interpreter;

public class EVAL {

    private static final String FORMAT = "%-5s | %-5s | %-5s | %s%n";

    public static void main(String[] args) {
        tabela("((a && b)||c)");
        tabela("a ? (b || c) : (b && c)");
        tabela("(a?1:0) + (b?1:0) + (c?1:0) >= 2");
    }

    private static void tabela(String expressao) {
        System.out.printf(FORMAT, "  a  ", "  b  ", "  c  ", expressao);
        System.out.printf(FORMAT, "-----", "-----", "-----", expressao.replaceAll(".", "-"));
        try {
            for (int i = 0; i < 8; i++) {
                boolean a = (i & (1<<2)) != 0;
                boolean b = (i & (1<<1)) != 0;
                boolean c = (i & (1<<0)) != 0;
                boolean r = eval(expressao, a, b, c);
                System.out.printf(FORMAT, a, b, c, r);
            }
        } catch (EvalError ex) {
            ex.printStackTrace();
        }
        System.out.println();
        System.out.println();
    }

    private static boolean eval(String expressao, boolean a, boolean b, boolean c) throws EvalError {
        Interpreter inter = new Interpreter();
        inter.set("a", a);
        inter.set("b", b);
        inter.set("c", c);
        Object resultado = inter.eval(expressao);
        return (Boolean) resultado;
    }
}

结果:

  a   |   b   |   c   | ((a && b)||c)
----- | ----- | ----- | -------------
false | false | false | false
false | false | true  | true
false | true  | false | false
false | true  | true  | true
true  | false | false | false
true  | false | true  | true
true  | true  | false | true
true  | true  | true  | true


  a   |   b   |   c   | a ? (b || c) : (b && c)
----- | ----- | ----- | -----------------------
false | false | false | false
false | false | true  | false
false | true  | false | false
false | true  | true  | true
true  | false | false | false
true  | false | true  | true
true  | true  | false | true
true  | true  | true  | true


  a   |   b   |   c   | (a?1:0) + (b?1:0) + (c?1:0) >= 2
----- | ----- | ----- | --------------------------------
false | false | false | false
false | false | true  | false
false | true  | false | false
false | true  | true  | true
true  | false | false | false
true  | false | true  | true
true  | true  | false | true
true  | true  | true  | true

1

我过去使用过JEval,发现它非常简单易用。这是一段代码片段:

import net.sourceforge.jeval.EvaluationException;
import net.sourceforge.jeval.Evaluator;

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println(new Evaluator().evaluate("5+4*3"));
        }
        catch (EvaluationException e) {
            e.printStackTrace();
        }
    }
}

1
最好使用库来完成这个任务。Janino 能够评估任意的 Java 表达式,包括你所指定的表达式以及更多其他类型的表达式。
请查看 ExpressionEvaluator 示例。

1

如果所有的表达式都是两个数字和一个运算符,那么也许可以。但在现实世界中,你期望从“5+4*3”得到什么结果呢?我会期望得到17而不是27,这意味着优先级很重要。优先级解析并不难,但肯定不是微不足道的。我赞同“使用库”的答案。 - user180247

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接