利用逆波兰表达式(后缀表达式)解析四则运算表达式的详细源代码及解释

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;


public class parseCalcString {
//   private static String strCalc = "6 * ( 5 + ( 2 + 3) * 8 + 3)";
   
   /**
    * 比较字符ch1 和ch2的优先级。如果ch1的优先级高,则返回true,直接入栈。否则,返回false
    * 因为对于四则运算,相同优先级是从左到右先运算
    * @param ch1 字符串中的元素
    * @param ch2 栈顶元素
    * @return
    */
   private static Boolean chkGreaterPriority(final char ch1, final  char ch2){
	   if(ch2 == '(' || ch2 == ')'){  //如果栈顶元素是这些元素,直接入栈
		   return true;  
	   }else if(ch1 == '*' || ch1 == '/'){
		   if(ch2 == '+' || ch2 == '-' ){
			   return true;
		   }else{
			   return false;
		   }
	   } 
		   return false;
	
   }
   
   /**
    * 中缀表达式转后缀表达式
    * @param strCalc
    * @return
    */
   @SuppressWarnings("unchecked")
   private final static List<String> midfixToSurfix(final String strCalc){

	   List<String> list = new ArrayList<String>();
	   @SuppressWarnings("rawtypes")
	   Stack st = new Stack();
	   StringBuffer sb = new StringBuffer();
	   
	   for(int i = 0 ; i < strCalc.length(); i++){
		  
		   char ch = strCalc.charAt(i);
		   //如果当前的字符串包含字母,则表示该字符串无法解析 排除E/e以支持科学计数法
		   if((ch != '.') && (ch > '9' || ch < '0' ) && ch != 'e' && ch != 'E' && ch != '(' && ch != ')' && ch != '+' && ch != '-' && ch != '*' && ch != '/' ){
			   return null;
		   }
		   //判断ch 是否是数字或小数点
//		   if(ch == '.' || (ch >='A' && ch <= 'Z')|| (ch >='a' && ch <= 'z')|| (ch >='0' && ch <= '9')){  //是否是字母、数字或小数点
		   if(ch == '.' || (ch >='0' && ch <= '9') ||ch == 'e' || ch == 'E'){
			    sb.append(ch);
			    continue;
		   }else if(ch == ' '){
			   continue;
		   }else{  //如果它不为数字、字母、及空格,则将stringbuffer当中的值放入list
			   
			   //将Stringbuffer 中的内容转换为字符串,存放到list中
			   if(sb.length() > 0){
				   list.add(sb.toString());
				   sb.setLength(0);
			   }
			   
			   if(st.isEmpty() || ch == '('){
				   st.push(ch);
			   }else if(ch == ')'){
				   // 输出栈中'(' 以上的值
				  while(!st.isEmpty() && (char)st.peek() != '('){
					  String str = String.valueOf(st.pop());
					  list.add(str);
				  }
				  st.pop(); //弹出“(”
				   
			   }else if(!st.isEmpty()  && !chkGreaterPriority(ch,(char)st.peek())){
				  
				   //需要将当前符号与栈顶元素的符号进行比较,根据优先级判断:如果ch的优先级比栈顶元素的优先级低或相等,则弹出栈顶元素,追加到list后,否则,ch入栈。
				   while(!st.isEmpty() && !chkGreaterPriority(ch,(char)st.peek())){
					   //如果当前符号的优先级比栈顶元素的优先级要高,则栈顶元素出栈,添加到list中
					   list.add(String.valueOf(st.pop()));
				   }
				   //将当前符号放入栈中
				   st.push(ch);
			   }else{
				   st.push(ch);
			   }
			   
		   }

	   }
	   list.add(sb.toString());
	   //将栈中的元素弹出,追加到list后,形成一个逆波兰表达式
	   while(!st.isEmpty()){
		   list.add(String.valueOf(st.pop()));
	   }
	    
      return list;
   }
   
   private final static BigDecimal getCalcResult(final List<String> resList ,Integer precision){
	   Stack<String> stack = new Stack<String>();
	   for(String str : resList){
		    if(str.equals("+")){
		    	BigDecimal d1 = new BigDecimal(stack.pop());
		    	BigDecimal d2 = new BigDecimal(stack.pop());
		    	stack.push(d2.add(d1).toString());
		    	
		    }else if(str.equals("-")){
		    	BigDecimal d1 = new BigDecimal(stack.pop());
		    	BigDecimal d2 = new BigDecimal(stack.pop());
		    	stack.push(d2.subtract(d1).toString());
	
		    }else if(str.equals("*")){
		   
		    	BigDecimal d1 = new BigDecimal(stack.pop());
		    	BigDecimal d2 = new BigDecimal(stack.pop());
		    	stack.push(d1.multiply(d2).toString());
		    	
		    }else if(str.equals("/")){
		     	BigDecimal d1 = new BigDecimal(stack.pop());
		     	//判断被除数是否为0
		     	if(d1.intValue() == 0){
		     		return null;
		     	}
		    	BigDecimal d2 = new BigDecimal(stack.pop());
		    	stack.push(d2.divide(d1, 2, RoundingMode.HALF_UP).toString());
		    }else{
		    	stack.push(str);
		    }
		    
	   }
	   Integer scale  =  precision == null?0:precision;
	   
	   BigDecimal res = new BigDecimal(stack.pop());
	   return res.setScale(scale,BigDecimal.ROUND_HALF_UP);
   }
 
   /**
    * 计算表达式的值
    * @param strCalc 待计算的表达式
    * @param scale 精确到小数点后多少位
    * @return
    */
   public static final BigDecimal calcExpStr(final String strCalc , final Integer precision){
	   List<String> resList =  midfixToSurfix(strCalc);
	   return getCalcResult(resList ,precision);
   }
   
public  static void main(String[] args){
	   String str ="66-11/44.62";
	   List<String> resList =  midfixToSurfix(str);
	   BigDecimal res = getCalcResult(resList,2);
	  
	   
	   //输出结果
	   System.out.println(res.toString());
   }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值