I tried making custom calculator with priorities -
and /
being greater then +
and *
.
It works nearly perfectly in that manner but I come to problem with unary minus. When it removes (), rather then for example from 1 + (-3), removing + and adding minus. It create this 1 + -3. Which whould cause -3 to not have priority of regular - , but rather secundary position of +. With that many math problems whould had diffrent solutions. Any idea how to solve it?
package A_2;
import java.util.*;
public class SimpleExpressionEvaluator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter an arithmetic expression:");
String expression = scanner.nextLine();
int result = evaluateExpression(expression);
System.out.println("Result: " + result);
}
public static int evaluateExpression(String expression) {
if (expression == null || expression.isEmpty()) {
throw new IllegalArgumentException("Expression cannot be null or empty");
}
String cleanedExpression = expression.replaceAll("\\s+", "");
List<String> tokens = tokenize(expression);
List<String> intermediate = new ArrayList<>(tokens);
Stack<Integer> openParenthesesIndices = new Stack<>();
for (int i = 0; i < intermediate.size(); i++) {
String token = intermediate.get(i);
if (token.equals("(")) {
openParenthesesIndices.push(i);
} else if (token.equals(")")) {
int openIndex = openParenthesesIndices.pop();
int result = evaluateSubExpression(intermediate.subList(openIndex + 1, i));
intermediate.subList(openIndex, i + 1).clear();
intermediate.add(openIndex, String.valueOf(result));
i = openIndex;
}
}
return evaluateSubExpression(intermediate);
}
private static List<String> preprocessTokens(List<String> tokens) {
List<String> processedTokens = new ArrayList<>();
for (int i = 0; i < tokens.size(); i++) {
String token = tokens.get(i);
if ((i == 0 && "-".equals(token)) || (i > 0 && "(".equals(tokens.get(i - 1)) && "-".equals(token))) {
processedTokens.add("0");
processedTokens.add("-");
} else {
processedTokens.add(token);
}
}
return processedTokens;
}
private static int evaluateSubExpression(List<String> tokens) {
tokens = preprocessTokens(tokens);
Stack<String> stack = new Stack<>();
for (int i = 0; i < tokens.size(); i++) {
String token = tokens.get(i);
if ("/".equals(token) || "*".equals(token) || "(".equals(token)) {
stack.push(token);
} else if ("-".equals(token) || "+".equals(token)) {
if (i > 0 && "+".equals(tokens.get(i - 1)) && "-".equals(token)) {
stack.pop();
System.out.println("Evaluating -: ");
} else {
stack.push(token);
}
} else if (")".equals(token)) {
int num = 0;
while (!stack.isEmpty() && !stack.peek().equals("(")) {
String op = stack.pop();
if (!stack.isEmpty()) { // Add this check
int val = Integer.parseInt(stack.pop());
if ("-".equals(op)) {
num -= val;
} else if ("/".equals(op)) {
num /= val;
}
}
}
if (!stack.isEmpty()) {
stack.pop();
}
if (i + 1 < tokens.size() && "-".equals(tokens.get(i + 1))) {
tokens.add(i + 1, Integer.toString(num));
tokens.add(i + 1, "-");
i++; // Skip the next '-' token
} else {
stack.push(Integer.toString(num));
}
System.out.println("Evaluating -: " + stack.toString());
} else {
// It's a number
int num = Integer.parseInt(token);
while (!stack.isEmpty() && ("/".equals(stack.peek()) || "-".equals(stack.peek()))) {
String op = stack.pop();
if ("-".equals(op)) {
num = Integer.parseInt(stack.pop()) - num;
}
else {
num = Integer.parseInt(stack.pop()) / num;
}
}
stack.push(Integer.toString(num));
System.out.println("Evaluating /: " + stack.toString());
}
}
// Second pass: Evaluate + and *
Queue<String> queue = new LinkedList<>(stack);
int result = Integer.parseInt(queue.poll());
while (!queue.isEmpty()) {
String op = queue.poll();
int num = Integer.parseInt(queue.poll());
if ("*".equals(op)) {
result *= num;
System.out.println("Evaluating *: " + result);
}
if ("+".equals(op)) {
result += num;
System.out.println("Evaluating +: " + result);
}
}
return result;
}
private static List<String> tokenize(String expression) {
List<String> tokens = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (Character.isDigit(ch) || (ch == '-' && (i == 0 || tokens.isEmpty() || tokens.get(tokens.size() - 1).equals("(")))) {
sb.append(ch);
} else {
if (sb.length() > 0) {
tokens.add(sb.toString());
sb.setLength(0);
}
if (ch == '-' && (i == 0 || tokens.isEmpty() || tokens.get(tokens.size() - 1).equals("("))) {
tokens.add(Character.toString(ch));
} else if (ch != ' ') {
tokens.add(Character.toString(ch));
}
}
}
if (sb.length() > 0) {
tokens.add(sb.toString());
}
return tokens;
}
I tried making fuctions which if character + is followed with negative number it whould also get priority, but I was unable to do it.
As I said previesly I want it to get priority of -, when () are removed so for example this math problem whould solve like this.
4 + 1 - 3 / 2 + 3 * 5 + (-5)
4 + -2/2 + 3 * 5 - 5
4 - 1 + 3 * 0
3
Rathen then currently whould whould be calculated like this
4 + 1 - 3 / 2 + 3 * 5 + (-5)
4 + -2/2 + 3 * 5 + -5
4 - 1 + 3 * 5 + -5
3 + 15 + -5
13