逆波兰式计算
import java.util.Stack; import java.util.StringTokenizer; /** * 逆波兰式计算 * java 运算公式运算得出结果 可以计算负数,保留小数位数 * @Date: 2018/9/6 11:41 * @Description: */ public class ReversePolishCalculate { private static final int One = 1; //规定优先级 最低 private static final int Two = 2; // private static final int Three = 3; //规定优先级 Three 最高 private static final int SCALE = 10; //保留小数位数 /** * 计算 逆波兰式 * @param formulaStr * @return * @throws Exception */ public static String reversePolishCalculate(String formulaStr) throws Exception { Stack<String> ysStack = new Stack<>(); // 定义一个运算栈 ArrayList<String> nblbdsList = zzHz(formulaStr);//得到逆波兰后缀 for(String nblbdsStr:nblbdsList){ if(isNum(nblbdsStr)){ ysStack.push(nblbdsStr); }else{ ysStack.push(String.valueOf(calculate(ysStack.pop(), ysStack.pop(), nblbdsStr))); } } return ysStack.pop(); //最后 栈中元素 即为结果 } /** * 判断 是否是数字 * @param str * @return */ public static boolean isNum(String str){ if(str.matches("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[0-9])|(0)")){ //这里使用正则表达式 验证是否是数字包含小数,0 return true; } return false; } /** * 判断 是否是操作符 * @param str * @return */ public static boolean isCzf(String str){ switch(str){ case "(": case "*": case "/": case "+": case "-": case ")":return true; default : return false; } } /** * 获取 优先级 * @param str * @return */ private static int getYxj(String str){ switch(str){ case "(":return Three; case "*": case "/":return Two; case "+": case "-":return One; case ")":return 0; default : return -1; } } /** * 判断优先级 * @param str1 * @param str2 * @return */ private static boolean isYxj(String str1,String str2){ return getYxj(str1) > getYxj(str2); } /** * 数字直接入nblbdsList * 运算符要与operators栈顶比较,优先级大则入栈,小于或等于但不是)则operators出栈到(后该操作符再入栈,如果是)则到(之后 * operators栈顶若是(则无条件入栈 * ********* 当 当前操作元素为 操作符时********** 这里是 核心代码, 用于操作符栈的判断 * @param czf * @param nblbdsList * @param czfStack */ private static void stackCzf(String czf,ArrayList<String> nblbdsList,Stack<String> czfStack){ //判断当前栈内是否为空 if(czfStack.isEmpty()){ czfStack.push(czf); return; } //判断是否为 ( if("(".equals(czf)){ czfStack.push(czf); return; } //判断是否为 ) if(")".equals(czf)){ String string = ""; while(!"(".equals(string = czfStack.pop())){ nblbdsList.add(string); } return; } //如果 当前栈顶元素是 ( 直接入栈 if("(".equals(czfStack.peek())){ czfStack.push(czf); return; } // 判断 与 栈顶元素的优先级 , > 为true if(isYxj(czf, czfStack.peek())){ czfStack.push(czf); return; } if(!isYxj(czf, czfStack.peek())){ nblbdsList.add(czfStack.pop()); stackCzf(czf,nblbdsList,czfStack); //这里调用函数 本身,并将本次的操作数传参 } } /** * * 逆波兰转换 * 中缀 —> 后缀 * @param formulaStr * @return * @throws Exception */ private static ArrayList<String> zzHz(String formulaStr) throws Exception { ArrayList<String> nblbdsList = new ArrayList<>(); // 存放转换后的 逆波兰式 Stack<String> czfStack = new Stack<>(); // 存放 运算符的栈 StringTokenizer stringTokenizer = new StringTokenizer(formulaStr, " +-*/()",true); Boolean preFlag = false; while(stringTokenizer.hasMoreTokens()) { //字符串分割 String currStr = stringTokenizer.nextToken(); if(isNum(currStr)){ nblbdsList.add(currStr); preFlag = false; continue; } if(isCzf(currStr)){ if("-".equals(currStr)&&preFlag){ nblbdsList.add("0"); } stackCzf(currStr,nblbdsList,czfStack); preFlag = true; continue; } if(" ".equals(currStr)){ continue; } throw new Exception("非法字符:"+currStr); } // 遍历完原始表达式后 将操作符栈内元素 全部添加至 逆波兰表达式list while(!czfStack.isEmpty()){ nblbdsList.add(czfStack.pop()); } return nblbdsList; } /** * 具体计算方法 * @param s1 * @param s2 * @param s3 * @return */ private static BigDecimal calculate(String s1, String s2, String s3){ BigDecimal one= new BigDecimal(s2); BigDecimal two= new BigDecimal(s1); switch(s3){ case "+":return one.add(two); case "-":return one.subtract(two); case "*":return one.multiply(two); case "/":return one.divide(two,SCALE,BigDecimal.ROUND_HALF_UP); default : return BigDecimal.ZERO; } } public static void main(String[] ars){ try { String a= ReversePolishCalculate.reversePolishCalculate("1+(1+1.5)"); System.out.println(a); } catch (Exception e) { e.printStackTrace(); } } }