0

I have a string that contains some mathematical formula which I want to execute dynamically and I want to store that value in a string. E.g.

String formula = "10 * 9";

... (execute somehow)

String result = "90"; (after successful execution).

I am using openjdk-18, therefore I cannot use ScriptEngine.

Is there any other way to do it?

Edit: possible operations: +, -, *, /, %, ^, brackets support

e.g. "((12/4) * (3 - 1) ^3)"

  • [jdk.jshell](https://docs.oracle.com/en/java/javase/18/docs/api/jdk.jshell/jdk/jshell/package-summary.html)? – teapot418 Mar 13 '23 at 22:00
  • I believe you need to use some listener so that your dynamic math formula method will be called when some condition is met based on the listener. There are many options out there, so I suggest looking based on that. – jesric1029 Mar 13 '23 at 22:17
  • Parsing and interpreting expressions is not simple. This is not the sort of thing that can be answered simply or easily in these types of formats. – sprinter Mar 13 '23 at 22:28
  • @sprinter operations (+, -, *, /, %, ^) and there are brackets Possible formula: "((12+3) * (18/6)^4)" – Biggy Poopa Mar 13 '23 at 23:03
  • @teapot418 Can one implement jshell as a singleton and pass the formula to the call method? I am not sure how can one do that. – Biggy Poopa Mar 13 '23 at 23:06
  • @jesric1029 thank you for the response. I tried various ways to implement it, unfortunately without a significant result. Therefore I would need some coding help. – Biggy Poopa Mar 13 '23 at 23:13
  • 1
    @BiggyPoopa you are looking for a simple solution to a complex problem. There really isn't one. Take a look at the shunting yard algorithm on wikipedia for a limited solution. But the answer given is correct: you ultimately need a parser – sprinter Mar 14 '23 at 06:36

1 Answers1

2

Well, you'll have to parse the String. This may be simple for the kind of forumula you're presenting in the question but may get a lot more complicated when it comes to nested expressions. In that case you might want to look at parse trees. Typically people use a tool like ANTLR which generates a parser for you if you give it a grammar. So lots of theoretical computer science stuff you would need to get your head around if you have not done so yet.

For your simple example however you could just split at space, then parse the first and last parts of the String as an int and then perform an operation based on the operator. This could look something like this:

public class Application {
    record ParsedExpression(int op1, int op2, String operator){};

    public static void main(String[] args) {
        final var sum = "10 + 5";
        final var difference = "10 - 5";

        System.out.println(calculate(parseMathExpression(sum)));
        System.out.println(calculate(parseMathExpression(difference)));
    }

    public static ParsedExpression parseMathExpression(String input){
        var expressionParts = input.split(" ");
        // you should catch NumberFormatException here!
        // you might also wanna do some validation here like checking the array length before accessing it
        final var x = Integer.parseInt(expressionParts[0]);
        final var y = Integer.parseInt(expressionParts[2]);
        final var operator = expressionParts[1];
        return new ParsedExpression(x, y, operator);
    }

    public static int calculate(ParsedExpression expression){
        return switch(expression.operator) {
            case "+" -> expression.op1 + expression.op2;
            case "-" -> expression.op1 - expression.op2;
            default -> throw new IllegalArgumentException("Unknown operator");
        };
    }
}

This is just a proof of concept. You will definitely need to add some error handling and validation (NumberFormatException, Overflows, ArrayIndexOutOfBoundsException etc.) here and you might expand on this to use other datatypes like double and add other operators like * or /.

Mushroomator
  • 6,516
  • 1
  • 10
  • 27
  • The problem is that I need to take care of various operations (+, -, *, /, %, ^) and there are brackets of course. I wanted to avoid dealing with parsing stuff from scratch, therefore I am looking for a simple solution to execute the formula. This could be a possible formula to execute "((12+3) * (18/6)^4)". – Biggy Poopa Mar 13 '23 at 23:02
  • 2
    I'm afraid in that case there is no way round it, I believe, as you have to have something like operator precedence and deep nesting etc.. But if you can can up with a grammar, which shouldn't be too hard and I am sure there is one out there already for this sort of problem (and likely also a parser) you might get up and running relatively quickly with ANTLR. – Mushroomator Mar 13 '23 at 23:04
  • 1
    Haven't had a proper look at this, but found it in a quick google search. Maybe this [Github repo](https://github.com/arothuis/antlr4-calculator) will give you an idea of what you are looking for. The grammar is quite straightforward. – Mushroomator Mar 13 '23 at 23:10
  • I am familiar with antlr4, but this would be way too complicated to implement for my purposes. I would need to implement an additional service in order to use this kind of parser. Right now, I am looking for a simpler solution. – Biggy Poopa Mar 13 '23 at 23:16
  • 1
    Check out [this method](https://stackoverflow.com/a/26227947/4725875). It works quite well and is easy to modify to suit your needs if need be. – DevilsHnd - 退職した Mar 14 '23 at 04:07