java計算表示式的值
package sweexamination.level1;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 轉為字尾表示式:
* 運算元直接放入結果
* 當前操作符與棧中的操作符比較:
* 棧空:進
* 當前高:進
* 當前低:將棧頂彈出,將當前放入結果(不會出項連續同級符號)
* 相等:彈出棧頂,然後進
* 左括號直接進棧,右括號將棧頂所有操作符彈出,直到遇到第一個左括號
* 掃描完成時,將棧頂符號直接彈出
*
*/
public class AA {
public int eval(String exp){
List<String> list = infixExpToPostExp(exp);// 轉化成字尾表示式
return doEval(list);// 真正求值
}
// 遇到運算元壓棧,遇到操作符從字尾表示式中彈出兩個數,計算出結果,壓入堆疊
private int doEval(List<String> list) {
Stack<String> stack = new Stack<String>();
String element;
int n1,n2,result;
try{
for(int i = 0; i < list.size();i++){
element = list.get(i);
if(isOperator(element)){
n1 = Integer.parseInt(stack.pop());
n2 = Integer.parseInt(stack.pop());
result = doOperate(n1,n2,element);
stack.push(new Integer(result).toString());
}else{
stack.push(element);
}
}
return Integer.parseInt(stack.pop());
}catch(RuntimeException e){
e.printStackTrace();
return -1;
}
}
private int doOperate(int n1, int n2, String operator) {
if(operator.equals("+"))
return n1 + n2;
else if(operator.equals("-"))
return n1 - n2;
else if(operator.equals("*"))
return n1 * n2;
else
return n1 / n2;
}
private boolean isOperator(String str){
return str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/");
}
private List<String> infixExpToPostExp(String exp){// 將中綴表示式轉化成為字尾表示式
List<String> postExp = new ArrayList<String>();// 存放轉化的字尾表示式的連結串列
StringBuffer numBuffer = new StringBuffer();// 用來儲存一個數的
Stack<Character> opStack = new Stack<Character>();// 操作符棧
char ch,preChar;
opStack.push('#');
try{
for(int i = 0; i < exp.length();){
ch = exp.charAt(i);
switch(ch){
case '+':
case '-':
case '*':
case '/':
preChar = opStack.peek();
// 如果棧裡面的操作符優先順序比當前的大,則把棧中優先順序大的都新增到字尾表示式列表中
while(priority(preChar) >= priority(ch)){
postExp.add(""+preChar);
opStack.pop();
preChar = opStack.peek();
}
opStack.push(ch);
i++;
break;
case '(':
// 左括號直接壓棧
opStack.push(ch);
i++;
break;
case ')':
// 右括號則直接把棧中左括號前面的彈出,並加入字尾表示式連結串列中
char c = opStack.pop();
while(c != '('){
postExp.add("" + c);
c = opStack.pop();
}
i++;
break;
// #號,代表表示式結束,可以直接把操作符棧中剩餘的操作符全部彈出,並加入字尾表示式連結串列中
case '#':
char c1;
while(!opStack.isEmpty()){
c1 = opStack.pop();
if(c1 != '#')
postExp.add("" + c1);
}
i++;
break;
// 過濾空白符
case ' ':
case '\t':
i++;
break;
// 數字則湊成一個整數,加入字尾表示式連結串列中
default:
if(Character.isDigit(ch)){
while(Character.isDigit(ch)){
numBuffer.append(ch);
ch = exp.charAt(++i);
}
postExp.add(numBuffer.toString());
numBuffer = new StringBuffer();
}else{
System.out.println("Illegal operator");
}
}
}
}catch(RuntimeException e){
e.printStackTrace();
}
return postExp;
}
private int priority(char op){// 定義優先順序
switch(op){
case'+':
case'-':
return 1;
case'*':
case'/':
return 2;
case'(':
case'#':
return 0;
}
System.out.println("Illegal operator");
return -1;
}
public static void main(String[] args) {
AA eval = new AA();
int result = eval.eval("2+3+55*22+21*2+(3+2)*3#");
System.out.println(result);
}
}