How to evaluate a math expression given in string form?

JavaStringMath

Java Problem Overview


I'm trying to write a Java routine to evaluate math expressions from String values like:

  1. "5+3"
  2. "10-40"
  3. "(1+10)*3"

I want to avoid a lot of if-then-else statements. How can I do this?

Java Solutions


Solution 1 - Java

With JDK1.6, you can use the built-in Javascript engine.

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));
    } 
}

Solution 2 - Java

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 like sqrt. It supports grouping using (...), and it gets the operator precedence and associativity rules correct.

public static double eval(final String str) {
	return new Object() {
		int pos = -1, ch;
		
		void nextChar() {
			ch = (++pos < str.length()) ? str.charAt(pos) : -1;
		}
		
		boolean eat(int charToEat) {
			while (ch == ' ') nextChar();
			if (ch == charToEat) {
				nextChar();
				return true;
			}
			return false;
		}
		
		double parse() {
			nextChar();
			double x = parseExpression();
			if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
			return x;
		}
		
		// Grammar:
		// expression = term | expression `+` term | expression `-` term
		// term = factor | term `*` factor | term `/` factor
		// factor = `+` factor | `-` factor | `(` expression `)` | number
		//        | functionName `(` expression `)` | functionName factor
		//        | factor `^` factor
		
		double parseExpression() {
			double x = parseTerm();
			for (;;) {
				if      (eat('+')) x += parseTerm(); // addition
				else if (eat('-')) x -= parseTerm(); // subtraction
				else return x;
			}
		}
		
		double parseTerm() {
			double x = parseFactor();
			for (;;) {
				if      (eat('*')) x *= parseFactor(); // multiplication
				else if (eat('/')) x /= parseFactor(); // division
				else return x;
			}
		}
		
		double parseFactor() {
			if (eat('+')) return +parseFactor(); // unary plus
			if (eat('-')) return -parseFactor(); // unary minus
			
			double x;
			int startPos = this.pos;
			if (eat('(')) { // parentheses
				x = parseExpression();
				if (!eat(')')) throw new RuntimeException("Missing ')'");
			} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
				while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
				x = Double.parseDouble(str.substring(startPos, this.pos));
			} else if (ch >= 'a' && ch <= 'z') { // functions
				while (ch >= 'a' && ch <= 'z') nextChar();
				String func = str.substring(startPos, this.pos);
				if (eat('(')) {
					x = parseExpression();
					if (!eat(')')) throw new RuntimeException("Missing ')' after argument to " + func);
				} else {
					x = parseFactor();
				}
				if (func.equals("sqrt")) x = Math.sqrt(x);
				else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
				else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
				else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
				else throw new RuntimeException("Unknown function: " + func);
			} else {
				throw new RuntimeException("Unexpected: " + (char)ch);
			}
			
			if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation
			
			return x;
		}
	}.parse();
}

Example:

System.out.println(eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2"));

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 deliberately kept it short, 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 a Map<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:

      @FunctionalInterface
      interface Expression {
      	double eval();
      }
    

    Now to rework the original "eval" function into a "parse" function, change all the methods that return doubles, so instead they return an instance of that interface. Java 8's lambda syntax works well for this. Example of one of the changed methods:

      Expression parseExpression() {
      	Expression x = parseTerm();
      	for (;;) {
      		if (eat('+')) { // addition
      			Expression a = x, b = parseTerm();
      			x = (() -> a.eval() + b.eval());
      		} else if (eat('-')) { // subtraction
      			Expression a = x, b = parseTerm();
      			x = (() -> a.eval() - b.eval());
      		} else {
      			return x;
      		}
      	}
      }
    

    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:

      public static void main(String[] args) {
      	Map<String,Double> variables = new HashMap<>();
      	Expression exp = parse("x^2 - x + 2", variables);
      	for (double x = -20; x <= +20; x++) {
      		variables.put("x", x);
      		System.out.println(x + " => " + exp.eval());
      	}
      }
    
  • Different datatypes:

    Instead of double, you could change the evaluator to use something more powerful like BigDecimal, or a class that implements complex numbers, or rational numbers (fractions). You could even use Object, 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!

Solution 3 - Java

For my university project, I was looking for a parser / evaluator supporting both basic formulas and more complicated equations (especially iterated operators). I found very nice open source library for JAVA and .NET called mXparser. I will give a few examples to make some feeling on the syntax, for further instructions please visit project website (especially tutorial section).

https://mathparser.org/

https://mathparser.org/mxparser-tutorial/

https://mathparser.org/api/

And few examples

1 - Simple furmula

Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()

2 - User defined arguments and constants

Argument x = new Argument("x = 10");
Constant a = new Constant("a = pi^2");
Expression e = new Expression("cos(a*x)", x, a);
double v = e.calculate()

3 - User defined functions

Function f = new Function("f(x, y, z) = sin(x) + cos(y*z)");
Expression e = new Expression("f(3,2,5)", f);
double v = e.calculate()

4 - Iteration

Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()

Found recently - in case you would like to try the syntax (and see the advanced use case) you can download the Scalar Calculator app that is powered by mXparser.

Solution 4 - Java

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.

Solution 5 - Java

HERE is another open source library on GitHub named 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.

Solution 6 - Java

You can evaluate expressions easily if your Java application already accesses a database, without using any other JARs.

Some databases require you to use a dummy table (eg, Oracle's "dual" table) and others will allow you to evaluate expressions without "selecting" from any table.

For example, in Sql Server or Sqlite

select (((12.10 +12.0))/ 233.0) amount

and in Oracle

select (((12.10 +12.0))/ 233.0) amount from dual;

The advantage of using a DB is that you can evaluate many expressions at the same time. Also most DB's will allow you to use highly complex expressions and will also have a number of extra functions that can be called as necessary.

However performance may suffer if many single expressions need to be evaluated individually, particularly when the DB is located on a network server.

The following addresses the performance problem to some extent, by using a Sqlite in-memory database.

Here's a full working example in Java

Class. forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount");
rs.next();
System.out.println(rs.getBigDecimal(1));
stat.close();
conn.close();

Of course you could extend the above code to handle multiple calculations at the same time.

ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");

Solution 7 - Java

You can also try the BeanShell interpreter:

Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));

Solution 8 - Java

Another way is to use the 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:

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

Solution 9 - Java

This article discusses various approaches. Here are the 2 key approaches mentioned in the article:

JEXL from Apache

Allows for scripts that include references to java objects.

// 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:
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();
    }
}

Solution 10 - Java

if we are going to implement it then we can can use the below algorithm :--

  1. While there are still tokens to be read in,

    1.1 Get the next token. 1.2 If the token is:

    1.2.1 A number: push it onto the value stack.
    
    1.2.2 A variable: get its value, and push onto the value stack.
    
    1.2.3 A left parenthesis: push it onto the operator stack.
    
    1.2.4 A right parenthesis:
    
      1 While the thing on top of the operator stack is not a 
        left parenthesis,
          1 Pop the operator from the operator stack.
          2 Pop the value stack twice, getting two operands.
          3 Apply the operator to the operands, in the correct order.
          4 Push the result onto the value stack.
      2 Pop the left parenthesis from the operator stack, and discard it.
    
    1.2.5 An operator (call it thisOp):
    
      1 While the operator stack is not empty, and the top thing on the
        operator stack has the same or greater precedence as thisOp,
        1 Pop the operator from the operator stack.
        2 Pop the value stack twice, getting two operands.
        3 Apply the operator to the operands, in the correct order.
        4 Push the result onto the value stack.
      2 Push thisOp onto the operator stack.
    
  2. While the operator stack is not empty, 1 Pop the operator from the operator stack. 2 Pop the value stack twice, getting two operands. 3 Apply the operator to the operands, in the correct order. 4 Push the result onto the value stack.

  3. At this point the operator stack should be empty, and the value stack should have only one value in it, which is the final result.

Solution 11 - Java

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:

  ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");  
  assertEquals(BigDecimal.valueOf(11), evalExpr.eval()); 

Solution 12 - Java

It seems like http://sourceforge.net/projects/jep/">JEP</a> should do the job

Solution 13 - Java

It's too late to answer but I came across same situation to evaluate expression in java, it might help someone

MVEL does runtime evaluation of expressions, we can write a java code in String to get it evaluated in this.

	String expressionStr = "x+y";
	Map<String, Object> vars = new HashMap<String, Object>();
	vars.put("x", 10);
	vars.put("y", 20);
	ExecutableStatement statement = (ExecutableStatement) MVEL.compileExpression(expressionStr);
	Object result = MVEL.executeExpression(statement, vars);

Solution 14 - Java

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

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".

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.

Solution 15 - Java

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; }
   //.........
}

Solution 16 - Java

You might have a look at the Symja framework:

ExprEvaluator util = new ExprEvaluator(); 
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30" 

Take note that definitively more complex expressions can be evaluated:

// D(...) gives the derivative of the function Sin(x)*Cos(x)
IAST function = D(Times(Sin(x), Cos(x)), x);
IExpr result = util.evaluate(function);
// print: Cos(x)^2-Sin(x)^2

Solution 17 - Java

package ExpressionCalculator.expressioncalculator;

import java.text.DecimalFormat;
import java.util.Scanner;

public class ExpressionCalculator {

private static String addSpaces(String exp){
	
	//Add space padding to operands.
	//https://regex101.com/r/sJ9gM7/73
	exp = exp.replaceAll("(?<=[0-9()])[\\/]", " / ");
	exp = exp.replaceAll("(?<=[0-9()])[\\^]", " ^ ");
	exp = exp.replaceAll("(?<=[0-9()])[\\*]", " * ");
	exp = exp.replaceAll("(?<=[0-9()])[+]", " + "); 
	exp = exp.replaceAll("(?<=[0-9()])[-]", " - ");

	//Keep replacing double spaces with single spaces until your string is properly formatted
	/*while(exp.indexOf("  ") != -1){
		exp = exp.replace("  ", " ");
	 }*/
	exp = exp.replaceAll(" {2,}", " ");
	
	   return exp;
}

public static Double evaluate(String expr){
	
	DecimalFormat df = new DecimalFormat("#.####");

	//Format the expression properly before performing operations
	String expression = addSpaces(expr);
	
    try {
        //We will evaluate using rule BDMAS, i.e. brackets, division, power, multiplication, addition and
        //subtraction will be processed in following order
        int indexClose = expression.indexOf(")");
        int indexOpen = -1;
        if (indexClose != -1) {
            String substring = expression.substring(0, indexClose);
            indexOpen = substring.lastIndexOf("(");
            substring = substring.substring(indexOpen + 1).trim();
            if(indexOpen != -1 && indexClose != -1) {
                Double result = evaluate(substring);
                expression = expression.substring(0, indexOpen).trim() + " " + result + " " + expression.substring(indexClose + 1).trim();
                return evaluate(expression.trim());
            }
        }

        String operation = "";
        if(expression.indexOf(" / ") != -1){
            operation = "/";
        }else if(expression.indexOf(" ^ ") != -1){
        	operation = "^";
        } else if(expression.indexOf(" * ") != -1){
            operation = "*";
        } else if(expression.indexOf(" + ") != -1){
            operation = "+";
        } else if(expression.indexOf(" - ") != -1){ //Avoid negative numbers
            operation = "-";
        } else{
            return Double.parseDouble(expression);
        }

        int index = expression.indexOf(operation);
        if(index != -1){
            indexOpen = expression.lastIndexOf(" ", index - 2);
            indexOpen = (indexOpen == -1)?0:indexOpen;
            indexClose = expression.indexOf(" ", index + 2);
            indexClose = (indexClose == -1)?expression.length():indexClose;
            if(indexOpen != -1 && indexClose != -1) {
                Double lhs = Double.parseDouble(expression.substring(indexOpen, index));
                Double rhs = Double.parseDouble(expression.substring(index + 2, indexClose));
                Double result = null;
                switch (operation){
                    case "/":
                        //Prevent divide by 0 exception.
                        if(rhs == 0){
                            return null;
                        }
                        result = lhs / rhs;
                        break;
                    case "^":
                        result = Math.pow(lhs, rhs);
                        break;
                    case "*":
                        result = lhs * rhs;
                        break;
                    case "-":
                        result = lhs - rhs;
                        break;
                    case "+":
                        result = lhs + rhs;
                        break;
                    default:
                        break;
                }
                if(indexClose == expression.length()){
                    expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose);
                }else{
                    expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose + 1);
                }
                return Double.valueOf(df.format(evaluate(expression.trim())));
            }
        }
    }catch(Exception exp){
        exp.printStackTrace();
    }
    return 0.0;
}

public static void main(String args[]){
	
	Scanner scanner = new Scanner(System.in);
	System.out.print("Enter an Mathematical Expression to Evaluate: ");
	String input = scanner.nextLine();
	System.out.println(evaluate(input));
}

}

Solution 18 - Java

Try the following sample code using JDK1.6's Javascript engine with code injection handling.

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class EvalUtil {
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
public static void main(String[] args) {
	try {
		System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || 5 >3 "));
		System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || true"));
	} catch (Exception e) {
		e.printStackTrace();
	}
}
public Object eval(String input) throws Exception{
    try {
	    if(input.matches(".*[a-zA-Z;~`#$_{}\\[\\]:\\\\;\"',\\.\\?]+.*")) {
		    throw new Exception("Invalid expression : " + input );
	    }
	    return engine.eval(input);
    } catch (Exception e) {
	    e.printStackTrace();
	    throw e;
    }
 }
}

Solution 19 - Java

This is actually complementing the answer given by @Boann. It has a slight bug which causes "-2 ^ 2" to give an erroneous result of -4.0. The problem for that is the point at which the exponentiation is evaluated in his. Just move the exponentiation to the block of parseTerm(), and you'll be all fine. Have a look at the below, which is @Boann's answer slightly modified. Modification is in the comments.

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch;

        void nextChar() {
            ch = (++pos < str.length()) ? str.charAt(pos) : -1;
        }

        boolean eat(int charToEat) {
            while (ch == ' ') nextChar();
            if (ch == charToEat) {
                nextChar();
                return true;
            }
            return false;
        }

        double parse() {
            nextChar();
            double x = parseExpression();
            if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
            return x;
        }

        // Grammar:
        // expression = term | expression `+` term | expression `-` term
        // term = factor | term `*` factor | term `/` factor
        // factor = `+` factor | `-` factor | `(` expression `)`
        //        | number | functionName factor | factor `^` factor

        double parseExpression() {
            double x = parseTerm();
            for (;;) {
                if      (eat('+')) x += parseTerm(); // addition
                else if (eat('-')) x -= parseTerm(); // subtraction
                else return x;
            }
        }

        double parseTerm() {
            double x = parseFactor();
            for (;;) {
                if      (eat('*')) x *= parseFactor(); // multiplication
                else if (eat('/')) x /= parseFactor(); // division
                else if (eat('^')) x = Math.pow(x, parseFactor()); //exponentiation -> Moved in to here. So the problem is fixed
                else return x;
            }
        }

        double parseFactor() {
            if (eat('+')) return parseFactor(); // unary plus
            if (eat('-')) return -parseFactor(); // unary minus

            double x;
            int startPos = this.pos;
            if (eat('(')) { // parentheses
                x = parseExpression();
                eat(')');
            } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                x = Double.parseDouble(str.substring(startPos, this.pos));
            } else if (ch >= 'a' && ch <= 'z') { // functions
                while (ch >= 'a' && ch <= 'z') nextChar();
                String func = str.substring(startPos, this.pos);
                x = parseFactor();
                if (func.equals("sqrt")) x = Math.sqrt(x);
                else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
                else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
                else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
                else throw new RuntimeException("Unknown function: " + func);
            } else {
                throw new RuntimeException("Unexpected: " + (char)ch);
            }

            //if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation -> This is causing a bit of problem

            return x;
        }
    }.parse();
}

Solution 20 - Java

A Java class that can evaluate mathematical expressions:

package test;

public class Calculator {

	public static Double calculate(String expression){
		if (expression == null || expression.length() == 0) {
			return null;
		}
		return calc(expression.replace(" ", ""));
	}
	public static Double calc(String expression) {
		String[] containerArr = new String[]{expression};
		double leftVal = getNextOperand(containerArr);
		expression = containerArr[0];
		if (expression.length() == 0) {
			return leftVal;
		}
		char operator = expression.charAt(0);
		expression = expression.substring(1);

		while (operator == '*' || operator == '/') {
			containerArr[0] = expression;
			double rightVal = getNextOperand(containerArr);
			expression = containerArr[0];
			if (operator == '*') {
				leftVal = leftVal * rightVal;
			} else {
				leftVal = leftVal / rightVal;
			}
			if (expression.length() > 0) {
				operator = expression.charAt(0);
				expression = expression.substring(1);
			} else {
				return leftVal;
			}
		}
		if (operator == '+') {
			return leftVal + calc(expression);
		} else {
			return leftVal - calc(expression);
		}

	}
	
	private static double getNextOperand(String[] exp){
		double res;
		if (exp[0].startsWith("(")) {
			int open = 1;
			int i = 1;
			while (open != 0) {
				if (exp[0].charAt(i) == '(') {
					open++;
				} else if (exp[0].charAt(i) == ')') {
					open--;
				}
				i++;
			}
			res = calc(exp[0].substring(1, i - 1));
			exp[0] = exp[0].substring(i);
		} else {
			int i = 1;
			if (exp[0].charAt(0) == '-') {
				i++;
			}
			while (exp[0].length() > i && isNumber((int) exp[0].charAt(i))) {
				i++;
			}
			res = Double.parseDouble(exp[0].substring(0, i));
			exp[0] = exp[0].substring(i);
		}
		return res;
	}


	private static boolean isNumber(int c) {
		int zero = (int) '0';
		int nine = (int) '9';
		return (c >= zero && c <= nine) || c =='.';
	}

	public static void main(String[] args) {
		System.out.println(calculate("(((( -6 )))) * 9 * -1"));
		System.out.println(calc("(-5.2+-5*-5*((5/4+2)))"));

	}

}

Solution 21 - Java

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 ..

Solution 22 - Java

It is possible to convert any expression string in infix notation to a postfix notation using Djikstra's shunting-yard algorithm. The result of the algorithm can then serve as input to the postfix algorithm with returns the result of the expression.

I wrote an article about it here, with an implementation in java

Solution 23 - Java

Yet another option: https://github.com/stefanhaustein/expressionparser

I have implemented this to have a simple but flexible option to permit both:

The TreeBuilder linked above is part of a CAS demo package that does symbolic derivation. There is also a BASIC interpreter example and I have started to build a TypeScript interpreter using it.

Solution 24 - Java

External library like RHINO or NASHORN can be used to run javascript. And javascript can evaluate simple formula without parcing the string. No performance impact as well if code is written well. Below is an example with RHINO -

public class RhinoApp {
    private String simpleAdd = "(12+13+2-2)*2+(12+13+2-2)*2";

public void runJavaScript() {
    Context jsCx = Context.enter();
    Context.getCurrentContext().setOptimizationLevel(-1);
    ScriptableObject scope = jsCx.initStandardObjects();
    Object result = jsCx.evaluateString(scope, simpleAdd , "formula", 0, null);
    Context.exit();
    System.out.println(result);
}

Solution 25 - Java

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class test2 {
    public static void main(String[] args) throws ScriptException {
        String s = "10+2";
        ScriptEngineManager mn = new ScriptEngineManager();
        ScriptEngine en = mn.getEngineByName("js");
        Object result = en.eval(s);
        System.out.println(result);
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShahView Question on Stackoverflow
Solution 1 - JavaRealHowToView Answer on Stackoverflow
Solution 2 - JavaBoannView Answer on Stackoverflow
Solution 3 - JavaLeroy KeganView Answer on Stackoverflow
Solution 4 - JavaGreg HewgillView Answer on Stackoverflow
Solution 5 - JavaTanvirView Answer on Stackoverflow
Solution 6 - JavaDABView Answer on Stackoverflow
Solution 7 - JavamarciowernerView Answer on Stackoverflow
Solution 8 - JavaFaheem SohailView Answer on Stackoverflow
Solution 9 - JavaBrad ParksView Answer on Stackoverflow
Solution 10 - JavaPrashant GautamView Answer on Stackoverflow
Solution 11 - JavaScorpionView Answer on Stackoverflow
Solution 12 - JavaBozhoView Answer on Stackoverflow
Solution 13 - JavaSaravanaView Answer on Stackoverflow
Solution 14 - JavaBruteForceView Answer on Stackoverflow
Solution 15 - JavastoneView Answer on Stackoverflow
Solution 16 - JavaLaurent MagninView Answer on Stackoverflow
Solution 17 - JavachejarasView Answer on Stackoverflow
Solution 18 - JavaBruceView Answer on Stackoverflow
Solution 19 - JavaRomeo SierraView Answer on Stackoverflow
Solution 20 - JavaEfi GView Answer on Stackoverflow
Solution 21 - JavakonxieView Answer on Stackoverflow
Solution 22 - JavaEmmanuel JohnView Answer on Stackoverflow
Solution 23 - JavaStefan HausteinView Answer on Stackoverflow
Solution 24 - JavaManishView Answer on Stackoverflow
Solution 25 - JavaAadol RrashidView Answer on Stackoverflow