我试图写一个Java例程来计算数学表达式从字符串值,如:

"5 + 3" "10-4 * 5" "(1 + 10) * 3"

我想避免很多如果-then-else语句。 我该怎么做呢?


当前回答

可以使用Djikstra的分流码算法将中缀表示法中的任何表达式字符串转换为后缀表示法。然后,算法的结果可以作为后缀算法的输入,并返回表达式的结果。

我在这里写了一篇关于它的文章,用java实现

其他回答

这样怎么样:

String st = "10+3";
int result;
for(int i=0;i<st.length();i++)
{
  if(st.charAt(i)=='+')
  {
    result=Integer.parseInt(st.substring(0, i))+Integer.parseInt(st.substring(i+1, st.length()));
    System.out.print(result);
  }         
}

并相应地对其他数学运算符做类似的事情。

解决这个问题的正确方法是使用词法分析器和解析器。您可以自己编写这些页面的简单版本,或者这些页面还包含指向Java词法分析器和解析器的链接。

创建递归下降解析器是非常好的学习练习。

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

public class test2 {
    public static void main(String[] args) throws ScriptException {
        String s = "10+2";
        ScriptEngineManager mn = new ScriptEngineManager();
        ScriptEngine en = mn.getEngineByName("js");
        Object result = en.eval(s);
        System.out.println(result);
    }
}

使用带有代码注入处理的JDK1.6 Javascript引擎尝试下面的示例代码。

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

public class EvalUtil {
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
public static void main(String[] args) {
    try {
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || 5 >3 "));
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || true"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public Object eval(String input) throws Exception{
    try {
        if(input.matches(".*[a-zA-Z;~`#$_{}\\[\\]:\\\\;\"',\\.\\?]+.*")) {
            throw new Exception("Invalid expression : " + input );
        }
        return engine.eval(input);
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
 }
}

下面是GitHub上另一个名为EvalEx的开源库。

与JavaScript引擎不同,这个库只专注于计算数学表达式。此外,该库是可扩展的,支持使用布尔运算符和圆括号。