Post

Created by @nathanedwards
 at November 15th 2023, 8:34:49 pm.

Question:

Write a Java program that takes an arithmetic expression as a string input and evaluates the result using the order of operations. The expression can consist of the following operators: addition (+), subtraction (-), multiplication (*), division (/), and parentheses. You need to implement the program to correctly handle the order of operations and parentheses.

Write the definition of the method evaluateExpression with the following signature:

public static double evaluateExpression(String expression)

Answer:

public class ExpressionEvaluator {

    public static double evaluateExpression(String expression) {
        Stack<Double> numbers = new Stack<>();
        Stack<Character> operators = new Stack<>();

        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);
            if (Character.isDigit(c)) {
                StringBuilder numBuilder = new StringBuilder();
                while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
                    numBuilder.append(expression.charAt(i++));
                }
                numbers.push(Double.parseDouble(numBuilder.toString()));
                i--;
            } else if (c == '(') {
                operators.push(c);
            } else if (c == ')') {
                while (operators.peek() != '(') {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.pop();
            } else if (c == '+' || c == '-' || c == '*' || c == '/') {
                while (!operators.isEmpty() && hasPrecedence(c, operators.peek())) {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.push(c);
            }
        }

        while (!operators.isEmpty()) {
            numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
        }

        return numbers.pop();
    }

    private static boolean hasPrecedence(char op1, char op2) {
        if (op2 == '(' || op2 == ')') {
            return false;
        }
        return (op1 != '*' && op1 != '/') || (op2 != '+' && op2 != '-');
    }

    private static double applyOperation(char operator, double b, double a) {
        switch (operator) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                if (b == 0) throw new UnsupportedOperationException("Cannot divide by zero");
                return a / b;
        }
        return 0;
    }

    public static void main(String[] args) {
       // Test the expression evaluation method 
      String expression = "3 + 4 * (2 - 1)";
      double result = evaluateExpression(expression);
      System.out.println("Result: " + result);
    }
}

Explanation:

  1. We use two stacks: one for numbers and one for operators.
  2. We iterate through the input string, one character at a time.
  3. If the character is a digit, we parse the number and push it onto the numbers stack.
  4. If the character is an open parenthesis, we push it onto the operators stack.
  5. If the character is a closing parenthesis, we pop operators and numbers from their respective stacks and perform the operation until we encounter an open parenthesis.
  6. If the character is an operator, we compare its precedence with the top of the operators stack, and perform operations accordingly.
  7. Once we finish iterating through the input string, we perform the remaining operations on the stacks until both are empty.
  8. The final answer is obtained from the top of the numbers stack and returned.

The main method in the ExpressionEvaluator class can be used to test the evaluateExpression method with a sample arithmetic expression.