Инфиксный алгоритм, возвращающий только последнее число - PullRequest
0 голосов
/ 22 января 2019

У меня есть следующий класс для вычисления формулы и возврата результата. Он использует infix algorithm и 2 разных стека для передачи значений и операторов. когда формула имеет пробелы , разделяющие символы, например: 2 + 3 * 4, она работает, но когда она не имеет пробелов, например: 2+3*4, она не работает. Мне нужна функциональность, чтобы работать без пробелов, но я не вижу, где мне нужно изменить код.

package calculator;

import java.util.Stack; 

public class EvaluateString 
{ 
    public static int evaluate(String expression) 
    { 
            System.out.println(expression);
        char[] tokens = expression.toCharArray(); 
                System.out.println(tokens);
        // Stack for numbers: 'values' 
        Stack<Integer> values = new Stack<Integer>(); 

        // Stack for Operators: 'ops' 
        Stack<Character> ops = new Stack<Character>(); 

        for (int i = 0; i < tokens.length; i++) 
        { 

            // Current token is a number, push it to stack for numbers 
            if (tokens[i] >= '0' && tokens[i] <= '9') 
            { 
                StringBuffer sbuf = new StringBuffer(); 
                // There may be more than one digits in number 
                while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9') 
                    sbuf.append(tokens[i++]); 
                values.push(Integer.parseInt(sbuf.toString())); 
            } 


            // Current token is an operator. 
            else if (tokens[i] == '+' || tokens[i] == '-' || 
                    tokens[i] == '*' || tokens[i] == '/') 
            { 
                // While top of 'ops' has same or greater precedence to current 
                // token, which is an operator. Apply operator on top of 'ops' 
                // to top two elements in values stack 
                while (!ops.empty() && hasPrecedence(tokens[i], ops.peek())) 
                values.push(applyOp(ops.pop(), values.pop(), values.pop())); 

                // Push current token to 'ops'. 
                ops.push(tokens[i]); 
            } 
        } 

        // Entire expression has been parsed at this point, apply remaining 
        // ops to remaining values 
        while (!ops.empty()) 
            values.push(applyOp(ops.pop(), values.pop(), values.pop())); 

        // Top of 'values' contains result, return it 
        return values.pop(); 
    } 

    // Returns true if 'op2' has higher or same precedence as 'op1', 
    // otherwise returns false. 
    public static boolean hasPrecedence(char op1, char op2) 
    { 

        if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) 
            return false; 
        else
            return true; 
    } 

    // A utility method to apply an operator 'op' on operands 'a' 
    // and 'b'. Return the result. 
    public static int applyOp(char op, int b, int a) 
    { 
        switch (op) 
        { 
        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; 
    } 

    // Driver method to test above methods 
    public static void main(String[] args) 
    { 
        System.out.println(EvaluateString.evaluate("100*2+12")); 
    } 
}

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Ваш второй оператор if для операций нажатия никогда не выполняется, поскольку вы фактически пропускаете операцию своим внутренним циклом while [i++]

 while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9') 
                sbuf.append(tokens[i++]); 

Но когда у вас есть пробелы, разделяющие символы , например,: 2 + 3 * 4 это работает, потому что вы еще не пропустили операцию с помощью [i++]

Вы можете просто decrease the counter после указания числа, которое нужно отправить в values стек

if (tokens[i] >= '0' && tokens[i] <= '9') 
        { 
            StringBuffer sbuf = new StringBuffer(); 
            // There may be more than one digits in number 
            while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9') 
                sbuf.append(tokens[i++]); 
            values.push(Integer.parseInt(sbuf.toString())); 
            --i;
        } 
0 голосов
/ 22 января 2019

Когда вы читаете номер, вы едите оператора, который следует.Вам нужно уменьшить i:

        if (tokens[i] >= '0' && tokens[i] <= '9') 
        { 
            StringBuffer sbuf = new StringBuffer(); 
            // There may be more than one digits in number 
            while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9') 
                sbuf.append(tokens[i++]); 
            values.push(Integer.parseInt(sbuf.toString())); 
            --i;
        } 
...