I'm trying to write a Java routine to evaluate simple math expressions from String
values like:
"5+3"
"10-40"
"10*3"
I want to avoid a lot of if-then-else statements. How can I do this?
I'm trying to write a Java routine to evaluate simple math expressions from String
values like:
"5+3"
"10-40"
"10*3"
I want to avoid a lot of if-then-else statements. How can I do this?
It seems like JEP should do the job
A Java class that can evaluate mathematical expressions:
The correct way to solve this is with a lexer and a parser. You can write simple versions of these yourself, or those pages also have links to Java lexers and parsers.
Creating a recursive descent parser is a really good learning exercise.
This is another interesting alternative https://github.com/Shy-Ta/expression-evaluator-demo
The usage is very simple and gets the job done, for example:
I've written this
eval
method for arithmetic expressions to answer this question. It does addition, subtraction, multiplication, division, exponentiation (using the^
symbol), and a few basic functions likesqrt
. It supports grouping using(
...)
, and it gets the operator precedence and associativity rules correct.Example:
Output: 7.5 (which is correct)
The parser is a recursive descent parser, so internally uses separate parse methods for each level of operator precedence in its grammar. I kept it short so it's easy to modify, but here are some ideas you might want to expand it with:
Variables:
The bit of the parser that reads the names for functions can easily be changed to handle custom variables too, by looking up names in a variable table passed to the
eval
method, such as aMap<String,Double> variables
.Separate compilation and evaluation:
What if, having added support for variables, you wanted to evaluate the same expression millions of times with changed variables, without parsing it every time? It's possible. First define an interface to use to evaluate the precompiled expression:
Now change all the methods that return
double
s, so instead they return an instance of that interface. Java 8's lambda syntax works great for this. Example of one of the changed methods:That builds a recursive tree of
Expression
objects representing the compiled expression (an abstract syntax tree). Then you can compile it once and evaluate it repeatedly with different values:Different datatypes:
Instead of
double
, you could change the evaluator to use something more powerful likeBigDecimal
, or a class that implements complex numbers, or rational numbers (fractions). You could even useObject
, allowing some mix of datatypes in expressions, just like a real programming language. :)All code in this answer released to the public domain. Have fun!
You can also try the BeanShell interpreter: