可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In one of my projects I want to add a feature where the user can provide in a formula, for example
sin (x + pi)/2 + 1
which I use in my Java app
/**
* The formula provided by the user
*/
private String formula; // = \"sin (x + pi)/2 + 1\"
/*
* Evaluates the formula and computes the result by using the
* given value for x
*/
public double calc(double x) {
Formula f = new Formula(formula);
f.setVar(\"x\", x);
return f.calc();
// or something similar
}
How can I evaluate math expressions?
回答1:
There\'s also exp4j, an expression evaluator based on Dijkstra\'s Shunting Yard
. It\'s freely available and redistributable under the Apache License 2.0, only about 25KB in size, and quite easy to use:
Calculable calc = new ExpressionBuilder(\"3 * sin(y) - 2 / (x - 2)\")
.withVariable(\"x\", varX)
.withVariable(\"y\", varY)
.build()
double result1=calc.calculate();
When using a newer API version like 0.4.8
:
Expression calc = new ExpressionBuilder(\"3 * sin(y) - 2 / (x - 2)\")
.variable(\"x\", x)
.variable(\"y\", y)
.build();
double result1 = calc.evaluate();
There\'s also a facility to use custom functions in exp4j.
回答2:
It depends how complex are the expressions you want to eval but for simple ones, java has a javascript engine that works pretty well:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName(\"JavaScript\");
// evaluate JavaScript code from String
Object obj = engine.eval(\"1+2\");
System.out.println( obj );
}
}
回答3:
To extend the list, I just have finished one, too:
https://github.com/uklimaschewski/EvalEx
EvalEx is a handy expression evaluator for Java, that allows to evaluate simple mathematical and boolean expressions.
Key Features:
- Uses BigDecimal for calculation and result
- Single class implementation, very compact
- No dependencies to external libraries
- Precision and rounding mode can be set
- Supports variables
- Standard boolean and mathematical operators
- Standard basic mathematical and boolean functions
- Custom functions and operators can be added at runtime
Examples:
BigDecimal result = null;
Expression expression = new Expression(\"1+1/3\");
result = expression.eval():
expression.setPrecision(2);
result = expression.eval():
result = new Expression(\"(3.4 + -4.1)/2\").eval();
result = new Expression(\"SQRT(a^2 + b^2\").with(\"a\",\"2.4\").and(\"b\",\"9.253\").eval();
BigDecimal a = new BigDecimal(\"2.4\");
BigDecimal b = new BigDecimal(\"9.235\");
result = new Expression(\"SQRT(a^2 + b^2\").with(\"a\",a).and(\"b\",b).eval();
result = new Expression(\"2.4/PI\").setPrecision(128).setRoundingMode(RoundingMode.UP).eval();
result = new Expression(\"random() > 0.5\").eval();
result = new Expression(\"not(x<7 || sqrt(max(x,9)) <= 3))\").with(\"x\",\"22.9\").eval();
回答4:
Nice math parser containing broad math collection - mXparser - please see the examples:
Example 1:
import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument(\"x = pi\");
Expression e = new Expression(\"sin(x + pi)/2 + 1\", x);
mXparser.consolePrintln(\"Res 1: \" + e.getExpressionString() + \" = \" + e.calculate());
x.setArgumentValue(2);
mXparser.consolePrintln(\"Res 2: \" + e.getExpressionString() + \" = \" + e.calculate());
Result:
[mXparser-v.4.0.0] Res 1: sin(x + pi)/2 + 1 = 1.0
[mXparser-v.4.0.0] Res 2: sin(x + pi)/2 + 1 = 0.545351286587159
Example 2:
import org.mariuszgromada.math.mxparser.*;
...
...
Function f = new Function(\"f(x) = sin(x + pi)/2 + 1\");
Expression e = new Expression(\"f(pi)\", f);
mXparser.consolePrintln(\"Res: \" + e.getExpressionString() + \" = \" + e.calculate());
Result:
[mXparser-v.4.0.0] Res: f(pi) = 1.0
For better understanding please follow mXparser tutorial and mXparser math collection.
Best regards
回答5:
I have a small-footprint yet very capable math evaluator which is completely unencumbered.
Primary Features
- Basic math operators, with inferred precedence (
+
-
*
×
/
÷
%
^
).
- Explicit precedence with parenthesis.
- Implicit multiplication of bracketed subexpressions.
- Correct right-associativity of exponentials (power operator).
- Direct support for hexadecimal numbers prefixed by
0x
.
- Constants and variables.
- Extensible functions.
- Extensible operators.
- Tiny 20 KiB footprint.
Here\'s a simple example which calculates the middle column of the subsection of a text display (biased left).
MathEval math=new MathEval();
math.setVariable(\"Top\", 5);
math.setVariable(\"Left\", 20);
math.setVariable(\"Bottom\",15);
math.setVariable(\"Right\", 60);
System.out.println(\"Middle: \"+math.evaluate(\"floor((Right+1-Left)/2)\")); // 20
回答6:
Adding another option to the list, I wrote Jep Java which gained a lot of popularity as an open source project on sourceforge.
It supports all the basic common tasks of expression parsing. But it also adds a lot of extendibility if you want to customize it. A lot of users have praised the library for being especially well written and easy to use. See the sourceforge reviews!
Here is a simple example with a single variable:
import com.singularsys.jep.Jep;
Jep jep = new Jep();
jep.addVariable(\"x\", 10);
jep.parse(\"x+1\");
Object result = jep.evaluate();
System.out.println(\"x + 1 = \" + result);
This will print \"x + 1 = 11\". You can change the value of variables and quickly evaluate the expression again.
I later also made the library available with a commercial license on the Singular Systems website.
回答7:
I already have posted a similar answer here. I just wanted to say that I have been worked on a little library that supports math, boolean and string expression evaluation. Here is a small example :
String expression = \"EXP(var)\";
ExpressionEvaluator evaluator = new ExpressionEvaluator();
evaluator.putVariable(new Variable(\"var\", VariableType.NUMBER, new BigDecimal(20)));
System.out.println(\"Value of exp(var) : \" + evaluator.evaluate(expression).getValue());
If you are interested, it is available here.