Question

Bear with me, I'm a little fried right now from getting this all together, but I'm at the final stretch. I've made a calculator in java that takes an infix equation and then changes it to postfix. It also takes variables! I'm made it so my postfix includes negative numbers from infix. This would look like so:

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

So obviously I got it working where negatives are '_' in postfix. Cool yeah? Ok, but now I gotta get my calculator to read them and I'm just getting brain-fart on where it goes on the stack and what I do to make it work without making a condition for all forms of operands. Here is what I have:

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;
    }

}

I would post less, but it all tends to work cohesively so I'll explain. Look closely at the method called evaluatePostfix() (it's the third one from the top).

This is where the class can take a postfix expression such as the one I named above and calculates it. It calculates an expression with all positive integers, but when I tried to implement it to change a number to negative before it actually ran any of the math, it goes kaputt.

Could anyone assist me with fixing this specific method so it works? I need it to calculate negative integers as well of positive.

Était-ce utile?

La solution

Basically the problem is in trying to pop from an empty stack for the '_' case. What you need to do is only attempt to pop op2 from the stack for the '*/+-' cases and not the '_' case.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top