Package org.apache.felix.gogo.runtime
Class Expression
java.lang.Object
org.apache.felix.gogo.runtime.Expression
EvalEx - Java Expression Evaluator
Introduction
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();
Supported Operators
| Mathematical Operators | |
|---|---|
| Operator | Description |
| + | Additive operator |
| - | Subtraction operator |
| * | Multiplication operator |
| / | Division operator |
| % | Remainder operator (Modulo) |
| ^ | Power operator |
| Boolean Operators* | |
|---|---|
| Operator | Description |
| = | Equals |
| == | Equals |
| != | Not equals |
| <> | Not equals |
| < | Less than |
| <= | Less than or equal to |
| > | Greater than |
| >= | Greater than or equal to |
| && | Boolean and |
| || | Boolean or |
Supported Functions
| Function* | Description |
|---|---|
| NOT(expression) | Boolean negation, 1 (means true) if the expression is not zero |
| IF(condition,value_if_true,value_if_false) | Returns one value if the condition evaluates to true or the other if it evaluates to false |
| RANDOM() | Produces a random number between 0 and 1 |
| MIN(e1,e2) | Returns the smaller of both expressions |
| MAX(e1,e2) | Returns the bigger of both expressions |
| ABS(expression) | Returns the absolute (non-negative) value of the expression |
| ROUND(expression,precision) | Rounds a value to a certain number of digits, uses the current rounding mode |
| FLOOR(expression) | Rounds the value down to the nearest integer |
| CEILING(expression) | Rounds the value up to the nearest integer |
| LOG(expression) | Returns the natural logarithm (base e) of an expression |
| SQRT(expression) | Returns the square root of an expression |
| SIN(expression) | Returns the trigonometric sine of an angle (in degrees) |
| COS(expression) | Returns the trigonometric cosine of an angle (in degrees) |
| TAN(expression) | Returns the trigonometric tangens of an angle (in degrees) |
| SINH(expression) | Returns the hyperbolic sine of a value |
| COSH(expression) | Returns the hyperbolic cosine of a value |
| TANH(expression) | Returns the hyperbolic tangens of a value |
| RAD(expression) | Converts an angle measured in degrees to an approximately equivalent angle measured in radians |
| DEG(expression) | Converts an angle measured in radians to an approximately equivalent angle measured in degrees |
Supported Constants
| Constant | Description |
|---|---|
| PI | The value of PI, exact to 100 digits |
| TRUE | The value one |
| FALSE | The value zero |
Add Custom Operators
Custom operators can be added easily, simply create an instance of `Expression.Operator` and add it to the expression. Parameters are the operator string, its precedence and if it is left associative. The operators `eval()` method will be called with the BigDecimal values of the operands. All existing operators can also be overridden.For example, add an operator `x >> n`, that moves the decimal point of _x_ _n_ digits to the right:
Expression e = new Expression("2.1234 >> 2");
e.addOperator(e.new Operator(">>", 30, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.movePointRight(v2.toBigInteger().intValue());
}
});
e.eval(); // returns 212.34
Add Custom Functions
Adding custom functions is as easy as adding custom operators. Create an instance of `Expression.Function`and add it to the expression. Parameters are the function name and the count of required parameters. The functions `eval()` method will be called with a list of the BigDecimal parameters. All existing functions can also be overridden.For example, add a function `average(a,b,c)`, that will calculate the average value of a, b and c:
Expression e = new Expression("2 * average(12,4,8)");
e.addFunction(e.new Function("average", 3) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal sum = parameters.get(0).add(parameters.get(1)).add(parameters.get(2));
return sum.divide(new BigDecimal(3));
}
});
e.eval(); // returns 16
The software is licensed under the MIT Open Source license (see LICENSE file).
- The *power of* operator (^) implementation was copied from [Stack Overflow](http://stackoverflow.com/questions/3579779/how-to-do-a-fractional-power-on-bigdecimal-in-java) Thanks to Gene Marin
- The SQRT() function implementation was taken from the book [The Java Programmers Guide To numerical Computing](http://www.amazon.de/Java-Number-Cruncher-Programmers-Numerical/dp/0130460419) (Ronald Mak, 2002)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionclassMarker class for assignment operators.classclassclassclassThe expression evaluators exception class.classAbstract definition of a supported expression function.classclassAbstract definition of a supported operator.(package private) static interfaceprivate classExpression tokenizer that allows to iterate over aStringexpression token by token.class -
Field Summary
FieldsModifier and TypeFieldDescriptionAll defined variables with name and value.private final charWhat character to use for decimal separators.private StringThe original infix expression.private Map<String,Expression.Function> All defined functions with name and implementation.private MathContextTheMathContextto use for calculations.private final charWhat character to use for minus sign (negative values).private Map<String,Expression.Operator> All defined operators with name and implementation.static final BigDecimalDefinition of PI as a constant, can be used in expressions as variable.private List<Expression.Token>The cached RPN (Reverse Polish Notation) of the expression. -
Constructor Summary
ConstructorsConstructorDescriptionExpression(String expression) Creates a new expression instance from an expression string. -
Method Summary
Modifier and TypeMethodDescriptionaddConstant(String name, Object value) Sets a constant value.addFunction(Expression.Function function) Adds a function to the list of supported functionsaddOperator(Expression.Operator operator) Adds an operator to the list of supported operators.eval()Evaluates the expression.Evaluates the expression.Get an iterator for this expression, allows iterating over an expression token by token.private List<Expression.Token>getRPN()Cached access to the RPN notation of this expression, ensures only one calculation of the RPN per expression instance.private booleanprivate booleanIs the string a number?setPrecision(int precision) Sets the precision for expression evaluation.setRoundingMode(RoundingMode roundingMode) Sets the rounding mode for expression evaluation.private List<Expression.Token>shuntingYard(String expression) Implementation of the Shunting Yard algorithm to transform an infix expression to a RPN expression.private BigDecimalprivate BigDecimaltoBigDecimal(Map<String, Object> variables, Object o) private NumbertoRPN()Get a string representation of the RPN (Reverse Polish Notation) for this expression.
-
Field Details
-
PI
Definition of PI as a constant, can be used in expressions as variable. -
mc
TheMathContextto use for calculations. -
expression
The original infix expression. -
rpn
The cached RPN (Reverse Polish Notation) of the expression. -
operators
All defined operators with name and implementation. -
functions
All defined functions with name and implementation. -
constants
All defined variables with name and value. -
decimalSeparator
private final char decimalSeparatorWhat character to use for decimal separators.- See Also:
-
minusSign
private final char minusSignWhat character to use for minus sign (negative values).- See Also:
-
-
Constructor Details
-
Expression
Creates a new expression instance from an expression string.- Parameters:
expression- The expression. E.g."2.4*sin(3)/(2-4)"or"sin(y)>0 & max(z, 3)>3"
-
-
Method Details
-
isNumber
Is the string a number?- Parameters:
st- The string.- Returns:
true, if the input string is a number.
-
isNumber
-
shuntingYard
Implementation of the Shunting Yard algorithm to transform an infix expression to a RPN expression.- Parameters:
expression- The input expression in infx.- Returns:
- A RPN representation of the expression, with each token as a list member.
-
eval
Evaluates the expression.- Returns:
- The result of the expression.
-
eval
Evaluates the expression.- Parameters:
variables- the variables- Returns:
- The result of the expression.
-
toResult
-
toBigDecimal
-
toBigDecimal
-
setPrecision
Sets the precision for expression evaluation.- Parameters:
precision- The new precision.- Returns:
- The expression, allows to chain methods.
-
setRoundingMode
Sets the rounding mode for expression evaluation.- Parameters:
roundingMode- The new rounding mode.- Returns:
- The expression, allows to chain methods.
-
addOperator
Adds an operator to the list of supported operators.- Parameters:
operator- The operator to add.- Returns:
- The previous operator with that name, or
nullif there was none.
-
addFunction
Adds a function to the list of supported functions- Parameters:
function- The function to add.- Returns:
- The previous operator with that name, or
nullif there was none.
-
addConstant
Sets a constant value.- Parameters:
name- The constant name.value- The constant value.- Returns:
- The expression, allows to chain methods.
-
getExpressionTokenizer
Get an iterator for this expression, allows iterating over an expression token by token.- Returns:
- A new iterator instance for this expression.
-
getRPN
Cached access to the RPN notation of this expression, ensures only one calculation of the RPN per expression instance. If no cached instance exists, a new one will be created and put to the cache.- Returns:
- The cached RPN instance.
-
toRPN
Get a string representation of the RPN (Reverse Polish Notation) for this expression.- Returns:
- A string with the RPN representation for this expression.
-