Java 如何评估以字符串形式给出的数学表达式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3422673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to evaluate a math expression given in string form?
提问by Shah
I'm trying to write a Java routine to evaluate simple math expressions from String
values like:
我正在尝试编写一个 Java 例程来评估来自以下String
值的简单数学表达式:
"5+3"
"10-40"
"10*3"
"5+3"
"10-40"
"10*3"
I want to avoid a lot of if-then-else statements. How can I do this?
我想避免很多 if-then-else 语句。我怎样才能做到这一点?
采纳答案by RealHowTo
With JDK1.6, you can use the built-in Javascript engine.
使用 JDK1.6,您可以使用内置的 Javascript 引擎。
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = "40+2";
System.out.println(engine.eval(foo));
}
}
回答by BruteForce
I think what ever way you do this it's going to involve a lot of conditional statements. But for single operations like in your examples you could limit it to 4 if statements with something like
我认为无论你怎么做,都会涉及很多条件语句。但是对于像您的示例中的单个操作,您可以将其限制为 4 个 if 语句,例如
String math = "1+4";
if (math.split("+").length == 2) {
//do calculation
} else if (math.split("-").length == 2) {
//do calculation
} ...
It gets a whole lot more complicated when you want to deal with multiple operations like "4+5*6".
当您想要处理诸如“4+5*6”之类的多个操作时,它会变得更加复杂。
If you are trying to build a calculator then I'd surgest passing each section of the calculation separatly (each number or operator) rather than as a single string.
如果您正在尝试构建一个计算器,那么我会单独传递计算的每个部分(每个数字或运算符),而不是作为单个字符串传递。
回答by Greg Hewgill
The correct way to solve this is with a lexerand a parser. You can write simple versions of these yourself, or those pages also have links to Java lexers and parsers.
解决这个问题的正确方法是使用lexer和parser。您可以自己编写这些的简单版本,或者这些页面也有指向 Java 词法分析器和解析器的链接。
Creating a recursive descent parser is a really good learning exercise.
创建递归下降解析器是一个非常好的学习练习。
回答by stone
import java.util.*;
public class check {
int ans;
String str="7 + 5";
StringTokenizer st=new StringTokenizer(str);
int v1=Integer.parseInt(st.nextToken());
String op=st.nextToken();
int v2=Integer.parseInt(st.nextToken());
if(op.equals("+")) { ans= v1 + v2; }
if(op.equals("-")) { ans= v1 - v2; }
//.........
}
回答by Brad Parks
This articlediscusses various approaches. Here are the 2 key approaches mentioned in the article:
本文讨论了各种方法。以下是文章中提到的 2 个关键方法:
JEXL from Apache
来自 Apache 的 JEXL
Allows for scripts that include references to java objects.
允许包含对 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);
Use the javascript engine embedded in the JDK:
使用嵌入在 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();
}
}
回答by marciowerner
回答by konxie
How about something like this:
这样的事情怎么样:
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);
}
}
and do the similar thing for every other mathematical operator accordingly ..
并相应地为每个其他数学运算符做类似的事情..
回答by Tanvir
HEREis another open source library on GitHub named EvalEx.
这里是 GitHub 上另一个名为 EvalEx 的开源库。
Unlike the JavaScript engine this library is focused in evaluating mathematical expressions only. Moreover, the library is extensible and supports use of boolean operators as well as parentheses.
与 JavaScript 引擎不同,该库仅专注于评估数学表达式。此外,该库是可扩展的,并支持使用布尔运算符和括号。
回答by Faheem Sohail
Another way is to use Spring Expression Language or SpEL which does a whole lot more along with evaluating mathematical expressions therefore maybe slightly overkill. You do not have to be using Spring framework to use this expression library as it is stand-alone. Copying examples from SpEL's documentation:
另一种方法是使用 Spring 表达式语言或 SpEL,它可以在评估数学表达式的同时做更多的事情,因此可能有点矫枉过正。您不必使用 Spring 框架来使用此表达式库,因为它是独立的。从 SpEL 的文档中复制示例:
ExpressionParser parser = new SpelExpressionParser();
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); //24.0
Read more concise SpEL examples hereand the complete docs here