四则运算中缀转后缀方法计算(推荐) 四则运算递归计算(不推荐,()层数越多就会越慢) 首先做好准备工作 1、二个数字计算方法体 2、运算符优先级的设定 3、打散字符串获得数字和字符的List集合(注意负值的分割点)
@Component public class Common { /** * 两位数double计算(或者用BigDecimal计算) * @param a1 * @param a2 * @param operator * @return * @throws Exception */ protected static double doubleCal(double a1, double a2, char operator) throws Exception{ switch (operator) { case '+': return a1 + a2; case '-': return a1 - a2; case '*': return a1 * a2; case '/': return a1 / a2; default: break; } throw new Exception("数据异常"); } /** * 获得优先级 * * @param s * @return * @throws Exception */ protected static int getPriority(String s) throws Exception{ // "null" 栈顶若为空,假设优先级为0, "(" 优先级设为1, "+-" 优先级设为2, "*/" 优先级设为3 if(s==null){ return 0; } switch(s) { case "(":return 1; case "+": case "-":return 2; case "*": case "/":return 3; default:break; } throw new Exception("数据异常"); } /** * 打散字符串获得数字和符号 * * @param str * @return */ protected static List<String> getList(String str){ char[] chars = str.toCharArray(); //标志 String sign = ""; //缓存正负号 String redis = ""; List<String> list = new ArrayList<>(); StringBuilder temporary = new StringBuilder(); for (char c : chars) { if (c >= '0' && c <= '9') { //是数字 if(StringUtil.isNotEmpty(redis)){ //有缓存符号数字加入正负号 temporary.append(redis + c); redis = ""; }else{ temporary.append(c); } sign = ""; } else if (c == '.') { //多小数点入参校验 if (temporary.indexOf(".") > 0) { System.out.println("入参错误"); } temporary.append(c); sign = ""; } else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') { //遇到符号从新记录数字,原数字加入list集合分开字符串 if (temporary.length() > 0) { list.add(temporary.toString()); temporary.setLength(0); } if(StringUtil.isNotEmpty(sign) && !sign.equals(")") && (c == '+' || c == '-')){ redis = c + ""; sign = ""; }else{ list.add(c + ""); } //记录标志 sign = c + ""; } else if (c == ' ') { //跳过空格 continue; } else { System.out.println("入参错误"); } } //最后一组数字 if (temporary.length() > 0) { list.add(temporary.toString()); } return list; } /** * 去除只包含一组数字的() * @param list * @return */ public static List<String> getList(List<String> list){ int a = 0; for (int i = 0; i < list.size(); i++) { String s = list.get(i); if (s.equals("(")) { a = i; } if (s.equals(")")) { if ((i - 2) == a) { list.remove(i); list.remove(a); } } } return list; } }
/** * 四则运算后缀方法计算 */ public class Test1 { public static void main(String[] args) throws Exception { String str = "2*2*((2*6)+(11+4))-6*-1"; List<String> list = Common.getList(str); String sufExpr = getSufExpr(list); String result = getResult(sufExpr); System.out.println(result); } /** * 中缀转后缀 * @param list * @return * @throws Exception */ private static String getSufExpr(List<String> list) throws Exception { /*返回结果字符串*/ StringBuilder sufExpr = new StringBuilder(); /*盛放运算符的栈*/ Stack<String> operator = new Stack<>(); /*在栈顶压入一个null假设优先级为0*/ operator.push(null); String topItem; for (String temp :list) { /*运算符*/ if (temp.matches("[+\\-*/()]")) { /*遇到左括号直接压栈*/ if (temp.equals("(")) { operator.push(temp); /*遇到右括号弹栈输出直到弹出左括号(不包括左括号)*/ } else if (temp.equals(")")) { while (!(topItem = operator.pop()).equals("(")) { sufExpr.append(topItem+" "); } } else { /*遇到运算符比较栈顶符号,若该运算符优先级大于栈顶直接压栈。若小于栈顶弹栈输出直到大于栈顶,然后将改运算符压栈*/ while(Common.getPriority(temp) <= Common.getPriority(operator.peek())) { sufExpr.append(operator.pop()+" "); } operator.push(temp); } }else { /*遇到数字直接输出*/ sufExpr.append(temp+" "); } } while(null != (topItem = operator.pop())) { sufExpr.append(topItem+" "); } return sufExpr.toString(); } /** * 解析后缀表达式 * @param sufExpr * @return * @throws Exception */ public static String getResult(String sufExpr) throws Exception { /*盛放数字栈*/ Stack<Double> number = new Stack<>(); /*这个正则匹配每个数字和符号*/ final Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?|[+\\-*/]"); Matcher m = pattern.matcher(sufExpr); while (m.find()) { String temp = m.group(); if (temp.matches("[+\\-*/]")) { /*遇到运算符,将最后两个数字取出,进行该运算,将结果再放入容器*/ double a1 = number.pop(); double a2 = number.pop(); double res = Common.doubleCal(a2, a1, temp.charAt(0)); number.push(res); } else { /*遇到数字直接放入容器*/ number.push(Double.valueOf(temp)); } } return number.pop() + ""; } }
/** * 四则运算递归方法计算 */ public class Test2 { public static void main(String[] args) throws Exception { String str = "2*2*((2*6)+(11+4))-6*-1"; List<String> list = Common.getList(str); String result = getResult(list).get(0); System.out.println(result); } private static List<String> getResult(List<String> list) throws Exception { //缓存数字 String num = ""; //缓存符号 String redis = ""; List<String> list1 = new ArrayList<>(); //计算乘除 String symbol = "[*/]"; Compute compute1 = new Compute(list, num, redis, list1, symbol).invoke(); num = compute1.getNum(); redis = compute1.getRedis(); //处理尾数 TailNum tailNum = null; tailNum = new TailNum(num, redis, list1).invoke(); num = tailNum.getNum(); redis = tailNum.getRedis(); //去掉只有一组数字的() list1 = Common.getList(list1); List<String> list2 = new ArrayList<>(); //计算加减 symbol = "[+\\-]"; Compute compute2 = new Compute(list1, num, redis, list2, symbol).invoke(); num = compute2.getNum(); redis = compute2.getRedis(); //处理尾数 tailNum = new TailNum(num, redis, list2).invoke(); num = tailNum.getNum(); redis = tailNum.getRedis(); //去掉只有一组数字的() list2 = Common.getList(list2); if(list2.size()>1){ //不是一个数字递归计算 list2 = getResult(list2); } return list2; } /** * 尾数加入集合并清除临时数据 */ private static class TailNum { private String num; private String redis; private List<String> list1; public TailNum(String num, String redis, List<String> list1) { this.num = num; this.redis = redis; this.list1 = list1; } public String getNum() { return num; } public String getRedis() { return redis; } public TailNum invoke() { if(!StringUtil.isEmpty(redis)){ list1.add(redis + ""); redis = ""; } if(!StringUtil.isEmpty(num)){ list1.add(num + ""); num = ""; } return this; } } /** * 返回结果存入缓存 */ private static class Compute { private List<String> list; private String num; private String redis; private List<String> list1; private String str; public Compute(List<String> list, String num, String redis, List<String> list1, String str) { this.list = list; this.num = num; this.redis = redis; this.list1 = list1; this.str = str; } public String getNum() { return num; } public String getRedis() { return redis; } public Compute invoke() throws Exception { for (String temp :list) { if (temp.matches("[+\\-*/()]")) { /*运算符*/ Symbol symbol = new Symbol(num, redis, list1, temp).invoke(str); num = symbol.getNum(); redis = symbol.getRedis(); }else{ /*数字*/ Num num1 = new Num(num, redis, temp).invoke(); num = num1.getNum(); redis = num1.getRedis(); } } return this; } } /** * 符号处理 */ protected static class Symbol { private String num; private String redis; private List<String> list; private String temp; public Symbol(String num, String redis, List<String> list, String temp) { this.num = num; this.redis = redis; this.list = list; this.temp = temp; } public String getNum() { return num; } public String getRedis() { return redis; } public Symbol invoke(String symbol) { if(temp.matches(symbol)){ if(StringUtil.isEmpty(redis)){ redis = temp; } }else{ if(!StringUtil.isEmpty(num)){ list.add(num + ""); } if(!StringUtil.isEmpty(redis)){ list.add(redis + ""); } list.add(temp + ""); num = ""; redis = ""; } return this; } } /** * 数字处理 */ protected static class Num { private String num; private String redis; private String temp; public Num(String num, String redis, String temp) { this.num = num; this.redis = redis; this.temp = temp; } public String getNum() { return num; } public String getRedis() { return redis; } public Num invoke() throws Exception { //缓存数字空则赋值,非空有缓存符号同时存在则计算结果并加入缓存,以供下一组数字计算用 if(StringUtil.isEmpty(num)){ num = temp; }else if(!StringUtil.isEmpty(redis)){ double a1 = Double.valueOf(num); double a2 = Double.valueOf(temp); double res = Common.doubleCal(a2, a1, redis.charAt(0)); num = res+""; redis = ""; } return this; } } }