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

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

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


当前回答

这样怎么样:

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

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

其他回答

你可以看看Symja框架:

ExprEvaluator util = new ExprEvaluator(); 
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30" 

请注意,可以计算更复杂的表达式:

// D(...) gives the derivative of the function Sin(x)*Cos(x)
IAST function = D(Times(Sin(x), Cos(x)), x);
IExpr result = util.evaluate(function);
// print: Cos(x)^2-Sin(x)^2

如果Java应用程序已经访问了数据库,则无需使用任何其他jar,就可以轻松地计算表达式。

一些数据库要求你使用一个虚拟表(例如,Oracle的“dual”表),而另一些数据库则允许你在不从任何表中“选择”的情况下计算表达式。

例如,在Sql Server或Sqlite中

select (((12.10 +12.0))/ 233.0) amount

在Oracle中

select (((12.10 +12.0))/ 233.0) amount from dual;

使用DB的优点是可以同时计算多个表达式。此外,大多数DB将允许您使用高度复杂的表达式,也将有许多额外的函数,可以在必要时调用。

但是,如果需要分别计算许多单个表达式,性能可能会受到影响,特别是当DB位于网络服务器上时。

下面通过使用Sqlite内存数据库在一定程度上解决了性能问题。

下面是一个完整的Java工作示例

Class. forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount");
rs.next();
System.out.println(rs.getBigDecimal(1));
stat.close();
conn.close();

当然,您可以扩展上面的代码以同时处理多个计算。

ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");

本文讨论了各种方法。以下是文中提到的两种关键方法:

Apache的JEXL

允许脚本包含对java对象的引用。

// Create or retrieve a JexlEngine
JexlEngine jexl = new JexlEngine();
// Create an expression object
String jexlExp = "foo.innerFoo.bar()";
Expression e = jexl.createExpression( jexlExp );
 
// Create a context and add data
JexlContext jctx = new MapContext();
jctx.set("foo", new Foo() );
 
// Now evaluate the expression, getting the result
Object o = e.evaluate(jctx);

使用JDK中嵌入的javascript引擎:

private static void jsEvalWithVariable()
{
    List<String> namesList = new ArrayList<String>();
    namesList.add("Jill");
    namesList.add("Bob");
    namesList.add("Laureen");
    namesList.add("Ed");
 
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
 
    jsEngine.put("namesListKey", namesList);
    System.out.println("Executing in script environment...");
    try
    {
      jsEngine.eval("var x;" +
                    "var names = namesListKey.toArray();" +
                    "for(x in names) {" +
                    "  println(names[x]);" +
                    "}" +
                    "namesListKey.add(\"Dana\");");
    }
    catch (ScriptException ex)
    {
        ex.printStackTrace();
    }
}

看来应该由JEP来做这项工作

我想无论你用什么方法做这个都会涉及到很多条件命题。但是对于单个操作,比如在你的例子中,你可以将它限制为4个if语句

String math = "1+4";

if (math.split("+").length == 2) {
    //do calculation
} else if (math.split("-").length == 2) {
    //do calculation
} ...

当你想要处理像“4+5*6”这样的多个操作时,它会变得更加复杂。

如果你试图构建一个计算器,那么我建议分别传递计算的每个部分(每个数字或运算符),而不是作为一个单一的字符串。