Утилита bc в Java, не работает в некоторых случаях

Я пытаюсь написать простую утилиту bc в Java. Моя программа работает нормально в большинстве случаев, но не работает для выражения 4+4*3-3-2-1/3. в основном подряд - операторы. не уверен, покрыл ли я все крайние случаи. любые предложения, чтобы сделать это лучше, были бы очень полезны. Спасибо

//ENUM for operations allowed.
private enum Operators {
    ADD         (1, "+"),
    SUBTRACT   (1, "-"),
    MULTIPLY    (2, "*"),
    DIVIDE      (2, "/");

    String operator;
    // Operator priority
    int weight;
    Operators(int w, String o) {
        this.operator = o;
        this.weight = w;
    }

    public String getOperator() {
        return operator;
    }

    public int getWeight() {
        return weight;
    }
}
// Stack and Queue to convert expression to postfix
LinkedList<String> resultQueue = new LinkedList<String>();
Stack<Operators> operatorStack = new Stack<Operators>();
//Stack to evaluate postfix expression
Stack<Integer> evalStack = new Stack<Integer>();

public int eval(String exp) {
    char[] expChar = exp.toCharArray();
    int i = 0;
    StringBuilder sb = new StringBuilder();
    while (i < expChar.length){
        if (expChar[i] >= '0' && expChar[i] <= '9') {
            sb.append(expChar[i]);

            if (i == expChar.length - 1) {
                resultQueue.add(sb.toString());
                while (!operatorStack.isEmpty()){
                    resultQueue.add(operatorStack.pop().getOperator());
                }
            }
        } else if (expChar[i] == '+' || expChar[i] == '-' || expChar[i] == '/' || expChar[i] == '*'){
            if (sb.length() > 0) {
                resultQueue.add(sb.toString());
                sb = new StringBuilder();
            }
                pushOperator(expChar[i]);
        } else
        return 0;
        i++;
    }
    for (String r : resultQueue){
        if (r.charAt(0) > '0' && r.charAt(0) < '9'){
            evalStack.push(Integer.valueOf(r));
        }else {
            try {
                int op2 = evalStack.pop();
                int op1 = evalStack.pop();
                if (r.charAt(0) == '+')
                    evalStack.push(Integer.valueOf(op1+op2));
                else if (r.charAt(0) == '-')
                    evalStack.push(Integer.valueOf(op1-op2));
                else if (r.charAt(0) == '/')
                    evalStack.push(Integer.valueOf(op1/op2));
                else if (r.charAt(0) == '*')
                    evalStack.push(Integer.valueOf(op1*op2));
            } catch (Exception e){
                System.out.println("Parse Error");
                return 0;
            }
        }
    }
    int result=0;
    try{
        result = evalStack.pop();
    }catch (Exception e){
        System.out.println("Parse Error");
    }

    return result;
}

private void pushOperator(char c) {
    Operators val = getOperator(c);
    if (operatorStack.isEmpty() || val.getWeight() >= operatorStack.peek().getWeight()){
        operatorStack.push(val);
    } else {
        while (!operatorStack.isEmpty() && val.getWeight() <= operatorStack.peek().getWeight()){
            resultQueue.add(operatorStack.pop().getOperator());
        }
        operatorStack.push(val);
    }
}

private Operators getOperator(char c) {
    for (Operators o: Operators.values()){
        if (o.getOperator().equals(String.valueOf(c)))
            return o;
    }
    throw new IllegalArgumentException("Operator not supported");
}

public static void main(String[] args) {

    BC bc = new BC();
    System.out.println("Please enter expression: ");
    Scanner scn = new Scanner(System.in);
    String exp = scn.nextLine();
    //remove white spaces
    exp = exp.replaceAll(" ", "");
    System.out.println("Result: " + bc.eval(exp));
    scn.close();
}

1 ответ

Решение

Проблема в том, что для последовательных минусовых операций вы вычисляете в неправильном направлении. Вы вычисляете справа налево, тогда как ваши потребности в компьютере слева направо.

Если у вас в стеке операнты 12 3 2 0 - - - Вы рассчитываете эффективно

12 - (3 - (2 - 0)) = 11

где правильно будет

12 - (3 + 2 + 0) = 7

Одним из возможных решений будет исправить это. Непосредственно перед тем, как вы начнете вычисления, вам нужно изменить операнты в стеке на 12 3 2 0 + + -,

Посмотрите этот фрагмент, который может быть выполнен до цикла вычислений.

// your code
...
    }
    i++;
}

for (i = 0; i < resultQueue.size() - 1; i++) {
    if ("-".equals(resultQueue.get(i)) && "-".equals(resultQueue.get(i+1))) {
        resultQueue.set(i, "+");
    }
}

// your code
for (String r : resultQueue) {
    if (r.charAt(0) > '0' && r.charAt(0) < '9') {
...
Другие вопросы по тегам