2

I am trying to write a program that will receive a function as a String and solve it. For ex. "5*5+2/2-8+5*5-2" should return 41

I wrote the code for multiplication and divisions and it works perfectly:

  public class Solver 
{
    public static void operationS(String m) 
    {
        ArrayList<String> z = new ArrayList<String>();
        char e= ' ';
        String x= " ";
        for (int i =0; i<m.length();i++)
        {
            e= m.charAt(i);
            x= Character.toString(e);


            z.add(x);
        }
         for (int i =0; i<z.size();i++)
            {
                System.out.print(z.get(i));
            }

        other(z);
    }

    public static void other(ArrayList<String> j)
    {
        int n1=0;
        int n2=0;
        int f=0;
        String n= " ";
          for (int m=0; m<j.size();m++)
          {

              if ((j.get(m)).equals("*"))
              {
                 n1 = Integer.parseInt(j.get(m-1));
                 n2 = Integer.parseInt(j.get(m+1));
                 f= n1*n2;
                 n = Integer.toString(f);

                 j.set(m,n);
                 j.remove(m+1);
                 j.remove(m-1);

                 m=0;
              }

              for (int e=0; e<j.size();e++)
              {

                  if ((j.get(e)).equals("/"))
                  {
                     n1 = Integer.parseInt(j.get(e-1));
                     n2 = Integer.parseInt(j.get(e+1));
                     f= n1/n2;
                     n = Integer.toString(f);

                     j.set(e,n);
                     j.remove(e+1);
                     j.remove(e-1);

                     e=0;
                  }

              }   
    }

          System.out.println();
          for (int i1 =0; i1<j.size();i1++)
            {
                System.out.print(j.get(i1)+",");
            }

However, for adding and subtracting, since there isnt an order for adding and subtracting, just whichever comes first, I wrote the following:

  int x1=0;
          int x2=0;
          int x3=0;
          String z = " ";

          for (int g=0; g<j.size();g++)
          {
              if ((j.get(g)).equals("+"))
              {
                  x1= Integer.parseInt(j.get(g-1));
                  x2= Integer.parseInt(j.get(g+1));
                  x3= x1+x2;
                  z = Integer.toString(x3);

                  j.set(g,z);
                  j.remove(g+1);
                  j.remove(g-1);

                  g=0;
              }
             g=0;

              if ((j.get(g)).equals("-"))
              {
                  x1= Integer.parseInt(j.get(g-1));
                  x2= Integer.parseInt(j.get(g+1));
                  x3= x1-x2;
                  z = Integer.toString(x3);

                  j.set(g,z);
                  j.remove(g+1);
                  j.remove(g-1);

                  g=0;
              }

              g=0;
          }

          System.out.println();
          for (int i1 =0; i1<j.size();i1++)
            {
                System.out.print(j.get(i1)+",");
            }

After this, it prints:

25,+,1,-,8,+,25,–,2,

. What am I doing wrong? Multiplication and dividing seem to be working perfectly

ZeldaX
  • 49
  • 9
  • Possible duplicate of [Evaluating a math expression given in string form](http://stackoverflow.com/questions/3422673/evaluating-a-math-expression-given-in-string-form) – TiyebM Sep 27 '16 at 13:43

5 Answers5

3

Going for an answer that doesn't help with your exact specific problem, but that hopefully helps you much further than that.

On a first glance, there are various problems with your code:

  1. Your are using super-short variable names all over the place. That saves you maybe 1 minute of typing overall; and costs you 5, 10, x minutes every time you read your code; or show it to other people. So: dont do that. Use names that say what the thing behind that name is about.
  2. You are using a lot of low-level code. You use a "couting-for" loop to iterate a list (called j, that is really really horrible!) for example. Meaning: you make your code much more complicated to read than it ought to be.
  3. In that way, it looks like nobody told you so far, but the idea of code is: it should be easy to read and understand. Probably you dont get grades for that, but believe me: in the long run, learning to write readable code is a super-important skill. If that got you curious, see if you can get a hand on "Clean code" by Robert Martin. And study that book. Then study it again. And again.

But the real problem is your approach to solve this problem. As I assume: this is some part of study assignment. And the next step will be that you don't have simple expressions such as "1+2*3"; but that you are asked to deal with something like "sqrt(2) + 3" and so on. Then you will be asked to add variables, etc. And then your whole approach breaks apart. Because your simple string operations won't do it any more.

In that sense: you should look into this question, and carefully study the 2nd answer by Boann to understand how to create a parser that dissects your input string into expressions that are then evaluated. Your code does both things "together"; thus making it super-hard to enhance the provided functionality.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • And you are setting `g=0` in your `for` loop, I think it's gonna be an infinite loop. – Shadov Sep 27 '16 at 13:28
  • @Whatzs I guess you want to "move" your comment to the question instead. I think you are "talking" to the wrong person here ;-) – GhostCat Sep 27 '16 at 13:32
  • because I want it to start checking from the beginning @Whatzs – ZeldaX Sep 27 '16 at 13:37
  • @ZeldaX No, the problem is that you wrote code that you don't understand what it is doing. That is the essential thing here. – GhostCat Sep 27 '16 at 13:41
3

You have 2 problems:

1) g=0; statements after if and else blocks will make you go into an infinite loop.

2) From the output you gave, the first minus (-) is Unicode character HYPHEN-MINUS (U+002D), while the second minus (–) is Unicode character EN DASH (U+2013), so (j.get(g)).equals("-") fails for the second minus as they are not equal.

uoyilmaz
  • 3,035
  • 14
  • 25
0

You can use the built-in Javascript engine

public static void main(String[] args) throws Exception{
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("JavaScript");
    String code = "5*5+2/2-8+5*5-2";
    System.out.println(engine.eval(code));
}
Tionio
  • 79
  • 3
  • It's for an assignment and I need to write it like I showed in the question. Thanks though @tionio – ZeldaX Sep 27 '16 at 14:00
0

Primarily Don't Repeat Yourself (the DRY principle). And use abstractions (full names, extracting methods when sensible). Static methods are a bit cumbersome, when using several methods. Here it is handy to use separate methods.

Maybe you want something like:

Solver solver = new Solver();
List<String> expr = solver.expression("5*5+2/2-8+5*5-2");
String result = solver.solve(expr);

A more abstract Solver class would do:

class Solver {

    List<String> expression(String expr) {
        String[] args = expr.split("\\b");
        List<String> result = new ArrayList<>();
        Collections.addAll(result, args);
        return result;
    }

    String solve(List<String> args) {
        solveBinaryOps(args, "[*/]");
        solveBinaryOps(args, "[-+]");
        return args.stream().collect(Collectors.joining(""));
    }

The above solveBinaryOps receives a regular expression pattern or alternatively simply in some form the operators you want to tackle. It takes care of operator precedence.

    private void solveBinaryOps(List<String> args, String opPattern) {
        for (int i = 1; i + 1 < args.length; ++i) {
            if (args.get(i).matches(opPattern)) {
                String value = evalBinaryOp(args.get(i - 1), args.get(i), args.get(i + 1));
                args.set(i, value);
                args.remove(i + 1);
                args.remove(i - 1);
                --i; // Continue from here.
            }
        }
    }

    private String evalBinaryOp(String lhs, String op, String rhs) {
        int x = Integer.parseInt(lhs);
        int y = Integer.parseInt(rhs);
        int z = 0;
        switch (op) {
        case "*":
            z = x * y;
            break;
        case "/":
            z = x / y;
            break;
        case "+":
            z = x + y;
            break;
        case "-":
            z = x - y;
            break;
        }
        return Integer.toString(z);
     }
}

The above can be improved at several points. But it is readable, and rewritable.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0
public class Solver {
public static void main(String args[]) {
    operation("5+2*5-6/2+1+5*12/3");
}

public static void operation(String m) {
    ArrayList<Object> expressions = new ArrayList<Object>();
    String e;
    String x = "";
    for (int i = 0; i < m.length(); i++) {
        e = m.substring(i, i + 1);
        if (!(e.equals("*") || e.equals("/") || e.equals("+") || e
                .equals("-"))) {
            x += e;
            continue;
        } else {
            if (!x.equals("") && x.matches("[0-9]+")) {
                int oper = Integer.parseInt(x);
                expressions.add(oper);
                expressions.add(m.charAt(i));
                x = "";
            }
        }
    }
    if (!x.equals("") && x.matches("[0-9]+")) {
        int oper = Integer.parseInt(x);
        expressions.add(oper);
        x = "";
    }
    for (int i = 0; i < expressions.size(); i++) {
        System.out.println(expressions.get(i));
    }
    evaluateExpression(expressions);
}

public static void evaluateExpression(ArrayList<Object> exp) {
    //Considering priorities we calculate * and / first and put them in a list mulDivList
    ArrayList<Object> mulDivList=new ArrayList<Object>();
    for (int i = 0; i < exp.size(); i++) {
        if (exp.get(i) instanceof Character) {
            if ((exp.get(i)).equals('*')) {
                int tempRes = (int) exp.get(i - 1) * (int) exp.get(i + 1);
                exp.set(i - 1, null);
                exp.set(i, null);
                exp.set(i + 1, tempRes);
            }
            else if ((exp.get(i)).equals('/')) {
                int tempRes = (int) exp.get(i - 1) / (int) exp.get(i + 1);
                exp.set(i - 1, null);
                exp.set(i, null);
                exp.set(i + 1, tempRes);
            }
        }
    }
    //Create new list with only + and - operations

    for(int i=0;i<exp.size();i++)
    {
        if(exp.get(i)!=null)
            mulDivList.add(exp.get(i));
    }
    //Calculate + and - .
    for(int i=0;i<mulDivList.size();i++)
    {
         if ((mulDivList.get(i)).equals('+')) {
            int tempRes = (int) mulDivList.get(i - 1) + (int) mulDivList.get(i + 1);
            mulDivList.set(i - 1, null);
            mulDivList.set(i, null);
            mulDivList.set(i + 1, tempRes);
        }
        else if ((mulDivList.get(i)).equals('-')) {
            int tempRes = (int) mulDivList.get(i - 1) - (int) mulDivList.get(i + 1);
            mulDivList.set(i - 1, null);
            mulDivList.set(i, null);
            mulDivList.set(i + 1, tempRes);
        }
    }
    System.out.println("Result is : " + mulDivList.get(mulDivList.size() - 1));

}
}
TiyebM
  • 2,684
  • 3
  • 40
  • 66