public static double evaluate(String expression) {
Deque<Double> operands = new ArrayDeque<>();
Deque<Character> operators = new ArrayDeque<>();
Deque<Character> precOperators = new ArrayDeque<>();
precOperators.push('('); // Push an opening parenthesis to ensure all operators are popped
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (Character.isDigit(c) || c == '.') {
// Parse the number and push it to the operand stack
int j = i;
while (j < expression.length() && (Character.isDigit(expression.charAt(j)) || expression.charAt(j) == '.')) {
j++;
}
double num = Double.parseDouble(expression.substring(i, j));
operands.push(num);
i = j - 1;
} else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '(') {
// Check if the '-' operator denotes a negative number or a subtraction
// operation
if (c == '-' && (i == 0 || (!Character.isDigit(expression.charAt(i - 1)) && expression.charAt(i - 1) != ')'))) {
// The '-' operator denotes a negative number, so parse the number and push it
// to the operand stack
int j = i + 1;
while (j < expression.length() && (Character.isDigit(expression.charAt(j)) || expression.charAt(j) == '.')) {
j++;
}
double num = Double.parseDouble(expression.substring(i, j));
operands.push(num);
i = j - 1;
} else {
// Push the operator to the operator stack in order of precedence
while (hasPrecedence(c, precOperators.peek())) {
char op = precOperators.pop();
double b = operands.pop();
double a = operands.pop();
double result = applyOp(op, a, b);
operands.push(result);
}
precOperators.push(c);
}
} else if (c == ')') {
// Pop operators and operands until we reach the matching '('
while (precOperators.peek() != '(') {
char op = precOperators.pop();
double b = operands.pop();
double a = operands.pop();
double result = applyOp(op, a, b);
operands.push(result);
}
precOperators.pop(); // Discard the '('
} else if (c == ' ') {
// Ignore whitespace
} else {
throw new IllegalArgumentException("Invalid operator: " + c);
}
}
// Perform any remaining operations
while (precOperators.size() > 1) {
char op = precOperators.pop();
double b = operands.pop();
double a = operands.pop();
double result = applyOp(op, a, b);
operands.push(result);
}
return operands.pop();
}