本程序先将需要运算的表达式转换成逆波兰表达式(即后缀表达式),据维基词条解释,逆波兰表示法不需要括号来标示操作符的优先级,逆波兰表达式使用栈很容易实现。
本代码已实现功能:带括号的整型表达式的四则运算(除法必须整除才符合常规想法),未实现功能:浮点计算
首先,将中缀表达式(即我们平时看到的正常表达式)转换成波兰式:
1.从左至右顺次读取表达式的字符,若是操作数加到波兰字串(用链表也可以),否则,2;
2.若操作符为‘(’或操作符栈(opS)为空,操作符入栈,否则,3;
3.若操作符为‘)’,将栈中遇到‘(’的操作符弹出并加到波兰字串尾部,将‘(’弹出(注意,此处不要追加到波
兰字串尾部),否则,4;
4.若栈顶为‘(’,将当前操作符压栈;否则,判断栈顶操作符和当前操作符的优先级,若栈顶优先级高,弹出并追加
到波兰字串尾部,直到栈顶优先级低于当前操作符优先级或栈为空,将当前操作符压栈,重复,1,直至表达式遍历
完成;
5.将操作符栈中的剩余操作符弹出并追加到波兰字串尾;
其次,计算波兰表达式:
这个利用栈可以很容易就实现:从左至右遍历波兰式,遇到数字就压入操作数栈(numS),若是操作符则弹出两个操作数并进行相应计算,计算结果压入栈中,这样一轮下来,栈中只剩一个数,而这个数即为整个表达式的结果。
这里需要主要的是:
1.判断表达式的合法性,我采用的是try-catch的方法,目前还没测试出什么bug,各位如有发现的话劳烦指出,谢谢!
2.当操作数为两位以上时的处理,具体见代码
3.这里说的是四则运算,即‘+’、‘-’、‘*’、‘/’,并未考虑类似于‘-2’这种情形
下面就展示一下我的代码:
package stack; public class BasicMath { char[] expch; private Stack<Integer> numS; private Stack<Character> opS; char[][] table = { { ' ', '+', '-', '*', '/'}, { '+', '>', '>', '<', '<'}, { '-', '>', '>', '<', '<'}, { '*', '>', '>', '>', '>'}, { '/', '>', '>', '>', '>'} }; public BasicMath() { numS = new Stack<Integer>(); opS = new Stack<Character>(); } public static void main(String[] args) { BasicMath bm = new BasicMath(); bm.getResult("3*(20-2)+6/2"); // test bm.getResult("(2+3))"); // test wrong expression bm.getResult("2/0"); // test divisor is zero } private char getPriority(char op1, char op2) { int i = 0, j = 0; while (i < 5) { if (table[i][0] == op1) { break; } i++; } while (j < 5) { if (table[0][j] == op2) { break; } j++; } return table[i][j]; } // get the postfix-expression of the normal expression private String getRpn(String exp) { String rpn = ""; expch = exp.toCharArray(); boolean isComplete = true; int tmp = 0; for (int i = 0; i < expch.length; i++) { if (expch[i] >= '0' && expch[i] <= '9') { if(isComplete) { tmp = expch[i] - 48; } else { tmp = tmp * 10 + (expch[i] - 48); } isComplete = false; } else { if(!isComplete) { rpn = rpn + tmp + " "; } isComplete = true; if (opS.isEmpty() || expch[i] == '(') { opS.push(expch[i]); } else if (expch[i] == ')') { while (!opS.isEmpty() && opS.getTop() != '(') { rpn = rpn + opS.pop() + " "; } opS.pop(); } else { if(opS.getTop()=='(') { opS.push(expch[i]); continue; } while (!opS.isEmpty() && opS.getTop()!='(' && getPriority(opS.getTop(), expch[i]) == '>') { rpn = rpn + opS.pop() + " "; } opS.push(expch[i]); } } } if(!isComplete) { rpn = rpn + tmp + " "; } while (!opS.isEmpty()) { rpn = rpn + opS.pop() + " "; } return rpn; } private void getResult(String exp) { String rpn = getRpn(exp); boolean isComplete = true; for(int i=0;i<rpn.length();i++) { if(rpn.charAt(i)>='0'&&rpn.charAt(i)<='9') { if(!isComplete) { numS.push(numS.pop()*10+(rpn.charAt(i)-48)); } else { numS.push(rpn.charAt(i)-48); } isComplete = false; } else { isComplete = true; if(rpn.charAt(i) == ' ') { ; } else { numS.push(calculate(rpn.charAt(i))); } } } System.out.println(numS.pop()); } // calculation private int calculate(char op) { try { int op1 = numS.pop(); int op2 = numS.pop(); switch(op) { case '+' : return op2+op1; case '-' : return op2-op1; case '*' : return op2*op1; case '/' : { if(op1 == 0) { System.out.print("Error:The divisor should not be zero!"+" "); } else { return op2/op1; } } } } catch(NullPointerException e) { System.out.print("Error:Wrong expression" + " "); } return -1; } }