我需要一个能够解析方程式的库,并给出输入结果。
例如:
String equation = "x + y + z";
Map<String, Integer> vars = new HashMap<String, Integer>();
vars.add("x", 2);
vars.add("y", 1),
vars.add("z", 3);
EquationSolver solver = new EquationSolver(equation, vars);
int result = solver.getResult();
System.out.println("result: " + result);
并评估为: 6
是否有任何类型的java库可以为我做到这一点?
由于
答案 0 :(得分:28)
您可以使用Java 1.6的脚本功能:
import javax.script.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("x", 2);
vars.put("y", 1);
vars.put("z", 3);
System.out.println("result = "+engine.eval("x + y + z", new SimpleBindings(vars)));
}
}
产生:
result = 6.0
对于更复杂的表达式,JEP是一个不错的选择。
答案 1 :(得分:17)
还有exp4j,一个基于Dijkstra的Shunting Yard的表达式评估器。它在Apache License 2.0下免费提供并可再发行,大小仅为25kb,非常易于使用。
Calculable calc = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
.withVariable("x", varX)
.withVariable("y", varY)
.build()
double result1=calc.calculate();
还可以在exp4j中使用自定义功能。
exp4j - evaluate math expressions
玩得开心!
答案 2 :(得分:2)
如果你想要高性能,我建议反对使用exp4j ,因为CogitoLearning类比exp4j快了大约2600倍(在1万次迭代上测试),是的你读得对。
通常,简单的表达式足以满足业务应用程序的需要。因此,CogitoLearning创建的库可能是更好的选择。
基准测试结果:
1000000 iterations to evaluate 200*(1+(pi/2))^2
Time Exp4J: 1.041117999977863E-5
Time JavaScript:4.532046999924487E-5 - 0.2297235664138545x slower than Exp4j
Time ExpCogit: 4.0000000000000036E-9 - 2602.794999944655x faster than Exp4j
对于Cogito库,请参阅http://cogitolearning.co.uk/docs/cogpar/index.html
请注意:测试用例并非完全纯粹用于评估JavaScript性能,因为我没有在这种情况下使用预构建的表达式。
使用的基准代码:
public class TestParser {
private static String exprStr = "200*(1+(pi/2))^2";
/**
* Exp4j
*/
private static ExpressionBuilder eb = new ExpressionBuilder(exprStr);
/**
* Cogit
*/
private static Parser parser = new Parser();
private static ExpressionNode expr = parser.parse(exprStr);
/**
* JavaScript
*/
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
private static Map<String, Object> vars = new HashMap<String, Object>();
public static void main(String[] args) throws UnknownFunctionException, UnparsableExpressionException, ScriptException {
int n = 1000000;
double t1 = 0d;
for(int i=1; i!=n; i++) {
t1+=getCalcTimeExp4J();
}
double r1=t1/n;
double t2 = 0d;
for(int i=1; i!=n; i++) {
t2+=getCalcTimeCogit();
}
double r2=t2/n;
double t3 = 0d;
for(int i=1; i!=n; i++) {
t3+=getCalcTimeJavaScriptEngine();
}
double r3=t3/n;
System.out.println(n + " iterations to evaluate " + exprStr);
System.out.println("Time Exp4J:\t" + r1);
System.out.println("Time JavaScript:" + r3 + " - " + r1/r3 + "x slower than Exp4j");
System.out.println("Time ExpCogit:\t" + r2 + " - " + r1/r2 + "x faster than Exp4j");
}
private static double getCalcTimeJavaScriptEngine() throws ScriptException {
long t = Util.nanotime();
vars.put("pi", Math.PI);
//Note that we're actually not using a pre-build expression here.
engine.eval(exprStr, new SimpleBindings(vars));
return(Util.nanotimeToSeconds(t));
}
private static double getCalcTimeCogit() {
long t = Util.nanotime();
expr.accept(new SetVariable("pi", Math.PI));
double r = expr.getValue();
return(Util.nanotimeToSeconds(t));
}
private static double getCalcTimeExp4J() throws UnknownFunctionException, UnparsableExpressionException {
long t = Util.nanotime();
Calculable calc = eb.withVariable("pi", Math.PI).build();
double r = calc.calculate();
return(Util.nanotimeToSeconds(t));
}
}
答案 3 :(得分:1)
请尝试mXparser,您可以在下面找到用法示例:
import org.mariuszgromada.math.mxparser.*;
...
...
String equation = "x + y + z";
Argument x = new Argument("x = 2");
Argument y = new Argument("y = 1");
Argument z = new Argument("z = 3");
Expression solver = new Expression(equation, x, y, z);
double result1 = solver.calculate();
System.out.println("result 1: " + result1);
x.setArgumentValue(3);
y.setArgumentValue(4);
z.setArgumentValue(5);
double result2 = solver.calculate();
System.out.println("result 2: " + result2);
结果:
result 1: 6.0
result 2: 12.0
这里mXparser的优点是mXparser只预编译一次表达式,然后,在参数值改变之后,计算速度非常快。
关注mXparser tutorial,mXparser math collection,mXparser API。
问候
答案 4 :(得分:0)
从问这个问题开始的八年后:如果您不想重新发明轮子,那里有很多奇特的数学解析器。
我几年前写的一篇文章支持算术运算,方程求解,微积分,积分微积分,基本统计量,函数/公式定义,图形等。
它叫ParserNG及其开源。
计算表达式非常简单:
MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22");
System.out.println("result: " + expr.solve());
result: 43.16981132075472
或者使用变量并计算简单表达式:
MathExpression expr = new MathExpression("r=3;P=2*pi*r;");
System.out.println("result: " + expr.getValue("P"));
或使用功能:
MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)");
System.out.println("result: " + expr.solve());
result: -10.65717648378352
或者在给定点上评估导数(请注意,它在幕后进行了符号微分(不是数字),因此精度不受数值近似误差的限制):
MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)");
System.out.println("result: " + expr.solve());
result: 38.66253179403897
在x = 3时一次区分 x^3 * ln(x)
。
您现在可以区分的次数是1。
或用于数值积分:
MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)");
System.out.println("result: " + expr.solve());
result: 7.999999999998261... approx: 8
此解析器非常快,并且具有许多其他功能。
免责声明:ParserNG是我创作的。