通过堆栈计算负数算术表达式

时间:2016-09-18 08:31:43

标签: java math stack operator-keyword

我需要你的帮助,计算负数。 我不能考虑负数。 我无法只计算正数。 如果你帮我修理它,我会很高兴的。

我想确定 - 代码的复杂性是O(n)?

import java.util.Stack;

public class Q2_M3 // O(N)
{
    public static double Calculate(String st) 
    {
        char[] Arr = st.toCharArray();  
        Stack<Double> values = new Stack<Double>();// Stack for numbers: 
        Stack<Character> oper = new Stack<Character>();// Stack for Operators:

    for (int i = 0; i < Arr.length; i++)
    {
        if (Arr[i] >= '0' && Arr[i] <= '9')
        {
            StringBuffer sbuf = new StringBuffer();
            while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))
                sbuf.append(Arr[i++]);
            values.push( Double.parseDouble(sbuf.toString()));
            i--;
        }
        // Current token is an opening brace, push it to 'oper'
        else if (Arr[i] == '(')
            oper.push(Arr[i]);

        // Closing brace encountered, solve entire brace
        else if (Arr[i] == ')')
        {
            while (oper.peek() != '(')
              values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
            oper.pop();
        }

        // Current token is an operator.
        else if (Arr[i] == '+' || Arr[i] == '-' ||
                 Arr[i] == '*' || Arr[i] == '/')
        {
            // While top of 'oper' has same or greater precedence to current
            // token, which is an operator. Apply operator on top of 'oper'
            // to top two elements in values stack
            while (!oper.empty() && hasPrecedence(Arr[i], oper.peek()))
              values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
            oper.push(Arr[i]);
        }
    }
    // Entire expression has been parsed at this point, apply remaining
    // oper to remaining values
    double val= 0;
    while (!oper.empty()){
        if(!values.isEmpty())
        //values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
        values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
        val=values.peek();
    }
    // Top of 'values' contains result, return it
    return val;
}

// Returns true if 'op2' has higher or same precedence as 'op1',
// otherwise returns false.
public static boolean hasPrecedence(char op1, char op2)
{
    if (op1 == '(' || op2 == '(' )
        return false;
    if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
        return false;
    else
        return true;
}

public static double doArithmetic(char oper, Double x, Double y)
{
    switch (oper)
    {
    case '+':
        return y + x;
    case '-':
        return y - x;
    case '*':
        return y * x;
    case '/':
        if (x == 0)
            System.out.println("Cannot divide by zero!");
        else
        return y / x;
    }
    return 0;
}

public static void main(String[] args)
{
    String st = "-5*(6+2)-12/4";
    String st2 = "20.2*(6.56567+2)-162/2";
    System.out.println(Calculate(st));
    System.out.println("Ans: "+Calculate(st2) );

}
}

2 个答案:

答案 0 :(得分:1)

所以你需要区分二元运算符a-b和一元运算符-c

就形式语法而言,您可以定义一个表达式,例如前缀是数字或 - 后跟数字

Expression :
    PrefixExpression
    Expression BinaryOp Expression
Prefix:
    NumberOrVar
    - NumberOrVar
    ( Expression )
NumberOrVar:
    0-9
    a-z

在代码中它变得像

Expression() {
  while(more tokens) {
    Prefix();
    Char op = next input item, will be an operator
    PushOperator(op)
    Prefix()
  }

}

Prefix() {
    Char c = next input
    if(c == '-') {
          PushOperator(UnitaryMinus)
          c = next input
    }
    if(c in 0-9 )
          values.push(c)
}

答案 1 :(得分:0)

首先

while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))

只会因为您的情况看起来像这样

if ((Arr[i] >= '0' && Arr[i] <= '9') || Arr[i] == '-')

唯一改变的是右边的东西。

我还更改了函数的开头,以便在-符号+-的任何地方替换,除了开头。

import java.util.*;
public class f {
    public static double Calculate(String st) {
        String pattern = "-";
        if (st.charAt(0)=='-')
            st = '-'+st.substring(1).replaceAll(pattern, "+-");
        else
            st = st.replaceAll(pattern, "+-");

        char[] Arr = st.toCharArray();
        Stack<Double> values = new Stack<>();// Stack for numbers:
        Stack<Character> oper = new Stack<>();// Stack for Operators:

        for (int i = 0; i < Arr.length; i++) {
            if ((Arr[i] >= '0' && Arr[i] <= '9') || Arr[i] == '-') {
                StringBuffer sbuf = new StringBuffer();
                while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))
                    sbuf.append(Arr[i++]);
                values.push( Double.parseDouble(sbuf.toString()));
                i--;
            }
            // Current token is an opening brace, push it to 'oper'
            else if (Arr[i] == '(')
                oper.push(Arr[i]);

            // Closing brace encountered, solve entire brace
            else if (Arr[i] == ')') {
                while (oper.peek() != '(')
                    values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
                oper.pop();
            }

            // Current token is an operator.
            else if (Arr[i] == '+' || Arr[i] == '-' || Arr[i] == '*' || Arr[i] == '/') {
                // While top of 'oper' has same or greater precedence to current
                // token, which is an operator. Apply operator on top of 'oper'
                // to top two elements in values stack
                while (!oper.empty() && hasPrecedence(Arr[i], oper.peek()))
                    values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
                oper.push(Arr[i]);
            }
        }
        // Entire expression has been parsed at this point, apply remaining
        // oper to remaining values
        double val= 0;
        while (!oper.empty()){
            if(!values.isEmpty())
                //values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
                values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
            val=values.peek();
        }
        // Top of 'values' contains result, return it
        return val;
    }

    // Returns true if 'op2' has higher or same precedence as 'op1',
    // otherwise returns false.
    public static boolean hasPrecedence(char op1, char op2) {
        if (op1 == '(' || op2 == '(' )
            return false;
        if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
            return false;
        else
            return true;
    }

    public static double doArithmetic(char oper, Double x, Double y) {
        switch (oper) {
            case '+':
                return y + x;
            case '-':
                return y - x;
            case '*':
                return y * x;
            case '/':
                if (x == 0)
                    System.out.println("Cannot divide by zero!");
                else
                    return y / x;
        }
        return 0;
    }

    public static void main(String[] args) {
        String st = "-5*(6+2)-12/4";
        String st2 = "20.2*(6.56567+2)-162/2";
        System.out.println(Calculate(st));
        System.out.println("Ans: "+Calculate(st2) );
    }
}

不确定这是否会使事情变得太慢,但它似乎适用于main方法中的测试用例。