表达式计算

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyParse {
 static Map<String, Integer> optrOrder;
 static {
  optrOrder = new HashMap<String, Integer>();
  optrOrder.put("(", 0);
  optrOrder.put("*", 1);
  optrOrder.put("/", 1);
  optrOrder.put("%", 1);
  optrOrder.put("+", 2);
  optrOrder.put("-", 2);
  optrOrder.put("^", 3);
  optrOrder.put("#", 3);
 }

 public static void main(String[] args) {
  List<String> tokens;
  try {
   // 词法分析
   tokens = lex("+2* (-2+3*4)+-5");
   // 中缀转后缀
   tokens = toRpn(tokens);
   // 计算结果
   System.out.println(calcRpn(tokens));
  }
  catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 /**
  * 将输入串转换为操作符串
  *
  * @param sExpres
  * @return
  */
 public static List<String> lex(String sExpres) {
  List<String> tokens = new ArrayList<String>();
  // 将表达式分割成符号序列
  String sRegExp = "(((?<=^|//(|//+|-|//*|/|%)(//+|-))?//d+(//.//d+)?)"
    + "|//(|//)|//*|/|//+|-";
  Pattern p = Pattern.compile(sRegExp);
  Matcher m = p.matcher(sExpres.replaceAll("//s+", ""));
  while (m.find()) {
   tokens.add(m.group());
  }
  tokens.add("#");
  return tokens;
 }

 /**
  * 将中缀表单时转化为后缀表达式
  *
  * @param tokens
  * @return
  */
 public static List<String> toRpn(List<String> tokens) throws Exception {
  List<String> rpnList = new ArrayList<String>();
  Stack<String> optrStack = new Stack<String>();
  optrStack.add("^");
  for(String token: tokens) {
   if(token.matches("^(//+|-)?//d+(//.//d+)?$")) {
    rpnList.add(token);
   }
   else {
    outputOptr(token, optrStack, rpnList);
   }
  }
  if(!optrStack.isEmpty() && optrStack.lastElement().equals("#")) {
   return rpnList;
  }
  else {
   throw new Exception("后缀表达式转化错误!");
  }
 }

 /**
  * 计算后缀表达式的值
  *
  * @param rpnTokens
  * @return
  * @throws Exception
  */
 public static double calcRpn(List<String> rpnTokens) throws Exception {
  NumberFormat nf = NumberFormat.getInstance();
  Stack<Double> numStack = new Stack<Double>();
  for(String token: rpnTokens) {
   if(token.matches("^(//+|-)?//d+(.//d+)?$")) {
    token = token.indexOf('+') == 0 ? token.substring(1) : token;
    numStack.add(nf.parse(token).doubleValue());
   }
   else {
    doCalcByOptr(token, numStack);
   }
  }
  if(!numStack.isEmpty() && numStack.size() == 1) {
   return numStack.lastElement();
  }
  else {
   throw new Exception("计算错误!");
  }
 }

 /**
  * 将运算符输出到后缀表达式序列.
  *
  * @param optr
  * @param optrStack
  * @param rpnList
  * @throws Exception
  */
 public static void outputOptr(String optr, Stack<String> optrStack,
   List<String> rpnList) throws Exception {
  String preOptr;
  if(optr.equals("(")) {// 处理左括号
   optrStack.push(optr);
   return;
  }
  if(optr.equals(")")) {// 处理右括号
   while (!optrStack.isEmpty()) {
    preOptr = optrStack.pop();
    if(!preOptr.equals("(")) {
     rpnList.add(preOptr);
    }
    else {
     break;
    }
   }
   if(optrStack.isEmpty()) {
    throw new Exception("括号未闭合!");
   }
   return;
  }
  /*
   * 按优先级处理其他运算符,若当前运算符优先级较高 直接入栈,否则将栈中运算符出战直至栈顶运算符 低于当前运算符
   */
  preOptr = optrStack.lastElement();
  if(optrCmp(optr, preOptr) < 0) {
   optrStack.push(optr);
  }
  else {
   while (!preOptr.equals("(") && !optrStack.isEmpty()
     && optrCmp(optr, preOptr) >= 0) {
    preOptr = optrStack.pop();
    if(!preOptr.equals("^")) {
     rpnList.add(preOptr);
    }
   }
   optrStack.push(optr);
  }
 }

 /**
  * 运算符优先级比较函数,optr1优先级大于optr2返回小于0值, 优先级相等返回0,optr1小于optr2返回大于0值.
  *
  * @param optr1
  * @param optr2
  * @return
  */
 public static int optrCmp(String optr1, String optr2) {
  int order1 = optrOrder.get(optr1);
  int order2 = optrOrder.get(optr2);
  return order1 - order2;
 }

 /**
  * 根据运算符对数据栈中的内容进行操作.
  *
  * @param optr
  * @param numStack
  */
 public static void doCalcByOptr(String optr, Stack<Double> numStack) {
  double n1, n2;
  n2 = numStack.pop();
  n1 = numStack.pop();
  if(optr.equals("+")) {
   numStack.push(n1 + n2);
  }
  else
   if(optr.equals("-")) {
    numStack.push(n1 - n2);
   }
   else
    if(optr.equals("*")) {
     numStack.push(n1 * n2);
    }
    else
     if(optr.equals("/")) {
      numStack.push(n1 / n2);
     }
     else
      if(optr.equals("%")) {
       numStack.push(n1 % n2);
      }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值