计算堆栈计算器中的负数

时间:2013-04-10 23:55:31

标签: java stack calculator negative-number postfix-notation

忍受我,我现在因为把这一切放在一起而有点油炸,但我已经到了最后阶段。我在java中制作了一个计算器,它采用了一个中缀方程,然后将其更改为后缀。它也需要变量!我做到了所以我的postfix包含来自中缀的负数。这看起来像这样:

infix: 1+-2*(4/2)
postfix: 12_42/*+

很明显,我在postfix中使用负数'_'时得到了它。很酷吗?好吧,但是现在我必须让我的计算器来阅读它们,而我只是在脑子里放置它在堆栈上的位置以及我做了什么使其工作而没有为所有形式的操作数制定条件。这就是我所拥有的:

import java.util.Stack;

/**
 *
 * @author rtibbetts268
 */
public class InfixToPostfix
{
        /**
         * Operators in reverse order of precedence.
         */
    private static final String operators = "-+/*_";
    private static final String operands = "0123456789x";

    /*public int evalInfix(String infix)
    {
        return evaluatePostfix(convert2Postfix(infix));
    }*/

    public String xToValue(String postfixExpr, String x)
    {
        char[] chars = postfixExpr.toCharArray();
        StringBuilder newPostfixExpr = new StringBuilder();

        for (char c : chars)
        {
            if (c == 'x')
            {
                newPostfixExpr.append(x);
            }
            else
            {
                newPostfixExpr.append(c);
            }
        }
        return newPostfixExpr.toString();
    }

    public String convert2Postfix(String infixExpr)
    {
        char[] chars = infixExpr.toCharArray();
        StringBuilder in = new StringBuilder(infixExpr.length());

        for (int i = 0; i<chars.length; i++)
        {
            if (infixExpr.charAt(i) == '-')
            {
                if (i == 0)
                {
                in.append('_');
                }
                else if(isOperand(infixExpr.charAt(i + 1)))
                {
                    if (i != infixExpr.length())
                    {
                    if (isOperator(infixExpr.charAt(i-1)))
                        in.append('_');
                    }
                    else
                    {
                        in.append(infixExpr.charAt(i));
                    }
                }
                else
                {
                   in.append(infixExpr.charAt(i));
                }
            }
            else
            {
                in.append(infixExpr.charAt(i));
            }
        }

        chars = in.toString().toCharArray();
        Stack<Character> stack = new Stack<Character>();
        StringBuilder out = new StringBuilder(in.toString().length());

        for (char c : chars)
        {
            if (isOperator(c))
            {
                while (!stack.isEmpty() && stack.peek() != '(')
                {
                    if (operatorGreaterOrEqual(stack.peek(), c))
                    {
                        out.append(stack.pop());
                    }
                    else
                    {
                        break;
                    }
                }
                stack.push(c);
            }
            else if (c == '(')
            {
                stack.push(c);
            }
            else if (c == ')')
            {
                while (!stack.isEmpty() && stack.peek() != '(')
                {
                    out.append(stack.pop());
                }
                if (!stack.isEmpty())
                {
                    stack.pop();
                }
            }
            else if (isOperand(c))
            {
                out.append(c);
            }
        }
        while (!stack.empty())
        {
            out.append(stack.pop());
        }
        return out.toString();
    }

    public int evaluatePostfix(String postfixExpr)//YBEYFCNUNKJKDV IT'S RIGHT HERE!!!
    {
        char[] chars = postfixExpr.toCharArray();
        Stack<Integer> stack = new Stack<Integer>();
        for (char c : chars)
        {
            if (isOperand(c))
            {
                stack.push(c - '0'); // convert char to int val
            }
            else if (isOperator(c))
            {
                int op1 = stack.pop();
                int op2 = stack.pop();
                int result;
                switch (c) {
                    case '_':
                        result = op1 * -1;
                        //stack.push(result);
                        //break;
                    case '*':
                        result = op1 * op2;
                        stack.push(result);
                        break;
                    case '/':
                        result = op2 / op1;
                        stack.push(result);
                        break;
                    case '+':
                        result = op1 + op2;
                        stack.push(result);
                        break;
                    case '-':
                        result = op2 - op1;
                        stack.push(result);
                        break;
                }
            }
        }
        return stack.pop();
    }

    private int getPrecedence(char operator)
    {
        int ret = 0;
        if (operator == '-' || operator == '+')
        {
            ret = 1;
        }
        else if (operator == '*' || operator == '/')
        {
            ret = 2;
        }
        if (operator == '_')
        {
            ret = 3;
        }
        return ret;
    }

    private boolean operatorGreaterOrEqual(char op1, char op2)
    {
        return getPrecedence(op1) >= getPrecedence(op2);
    }

    private boolean isOperator(char val)
    {
        return operators.indexOf(val) >= 0;
    }

    private boolean isOperand(char val)
    {
        return operands.indexOf(val) >= 0;
    }

}

我会少发帖,但这一切都倾向于凝聚力,所以我会解释。仔细查看名为evaluatePostfix()的方法(它是从顶部开始的第三个方法)。

这是类可以采用后缀表达式的地方,例如我在上面命名的表达式并计算它。它计算一个带有所有正整数的表达式,但当我尝试实现它以在实际运行任何数学运算之前将数字更改为负数时,它就会变成kaputt。

任何人都可以帮我修复这个特定的方法吗?我需要它来计算负整数以及正整数。

1 个答案:

答案 0 :(得分:2)

基本上问题是尝试从空堆栈弹出'_'的情况。你需要做的只是尝试从堆栈中为'* / + - '案例而不是'_'案例弹出op2。

public int evaluatePostfix(String postfixExpr)
{
    char[] chars = postfixExpr.toCharArray();
    Stack<Integer> stack = new Stack<Integer>();
    for (char c : chars)
    {
        if (isOperand(c))
        {
            stack.push(c - '0'); // convert char to int val
        }
        else if (isOperator(c))
        {
            int op1 = stack.pop();
            int op2;
            int result;
            switch (c) {
                case '_':
                    result = op1 * -1;
                    stack.push(result);
                    break;
                case '*':
                    op2 = stack.pop();
                    result = op1 * op2;
                    stack.push(result);
                    break;
                case '/':
                    op2 = stack.pop();
                    result = op2 / op1;
                    stack.push(result);
                    break;
                case '+':
                    op2 = stack.pop();
                    result = op1 + op2;
                    stack.push(result);
                    break;
                case '-':
                    op2 = stack.pop();
                    result = op2 - op1;
                    stack.push(result);
                    break;
            }
        }
    }
    return stack.pop();
}