1 import java.math.BigDecimal; 2 import java.util.ArrayList; 3 import java.util.List; 4 import java.util.Stack; 5 import java.util.regex.Matcher; 6 import java.util.regex.Pattern; 7 8 9 public class Calu { 10 private static List<String> sysboList=new ArrayList<String>(){{ 11 this.add("+"); 12 this.add("-"); 13 this.add("*"); 14 this.add("/"); 15 this.add("="); 16 }}; 17 private static Pattern p1 = Pattern.compile("(^[0-9]{1,9}[.][0-9]{1,2}$)|(^[0-9]{1,11}$)"); 18 19 public static void main(String[] args) { 20 String numstr="(2+2*(1+2))*3/2"; 21 System.out.println(result(numstr)); 22 } 23 24 public static BigDecimal result(String numstr){ 25 //先把括号中的值给算出来然后替换,找的括号是最小范围的 26 //最后一个'('出现的位置 到 第一个')'出现的位置 27 StringBuffer sb=new StringBuffer(numstr); 28 if(isStandard(sb.toString())){ 29 String rs=bracketsString(sb); 30 while(rs!=null){ 31 BigDecimal calBracketsValue = calBracketsValue(rs+"="); 32 sb.replace(sb.indexOf("@"), sb.indexOf("@")+1, calBracketsValue.toString()); 33 System.out.println(sb); 34 rs=bracketsString(sb); 35 } 36 return calBracketsValue(sb.toString()+"="); 37 } 38 return new BigDecimal("0"); 39 } 40 41 public static String bracketsString(StringBuffer str){ 42 int leftBracketsPoint=str.lastIndexOf("("); 43 int rightBracketsPoint=str.indexOf(")"); 44 if(leftBracketsPoint==-1 || rightBracketsPoint==-1){ 45 return null; 46 } 47 String res= str.substring(leftBracketsPoint+1,rightBracketsPoint); 48 str.replace(leftBracketsPoint, rightBracketsPoint+1, "@"); 49 return res; 50 } 51 52 //计算括号中的表达式的值 53 public static BigDecimal calBracketsValue(String numStr){ 54 Stack<BigDecimal> numStack=new Stack<BigDecimal>();//数字栈 55 Stack<String> sysmboStack=new Stack<String>();//符号栈 56 int lastSysboPoint=0;//上一次非数字出现的位置 57 for(int i=0;i<numStr.length();i++){ 58 String ch=numStr.charAt(i)+""; 59 if(sysboList.contains(ch)){ 60 //开始计算入栈 61 //先把前面的数字入栈 1+1*1= 62 String num=numStr.substring(lastSysboPoint,i); 63 numStack.push(new BigDecimal(num)); 64 65 while(!sysmboStack.isEmpty() && !comparePri(ch.charAt(0),sysmboStack.peek().charAt(0))){//如果符号栈不为空,就把前一个符号拿出来和现在的符号做优先级对比 66 BigDecimal num2=numStack.pop(); 67 BigDecimal num1=numStack.pop(); 68 String sysboTemp=sysmboStack.pop(); 69 if(sysboTemp.equals("+")){ 70 numStack.push(num1.add(num2)); 71 }else if(sysboTemp.equals("-")){ 72 numStack.push(num1.subtract(num2)); 73 }else if(sysboTemp.equals("*")){ 74 numStack.push(num1.multiply(num2)); 75 }else if(sysboTemp.equals("/")){ 76 numStack.push(num1.divide(num2,10,BigDecimal.ROUND_HALF_DOWN)); 77 } 78 } 79 sysmboStack.push(ch); 80 lastSysboPoint=i+1; 81 } 82 } 83 84 return numStack.pop(); 85 } 86 87 88 89 private static boolean comparePri(char symbol,char top) { 90 if (top == '(') { 91 return true; 92 } 93 // 比较优先级 94 switch (symbol) { 95 case '(': // 优先级最高 96 return true; 97 case '*': { 98 if (top == '+' || top == '-') // 优先级比+和-高 99 return true; 100 else 101 return false; 102 } 103 case '/': { 104 if (top == '+' || top == '-') // 优先级比+和-高 105 return true; 106 else 107 return false; 108 } 109 case '+': 110 return false; 111 case '-': 112 return false; 113 case ')': // 优先级最低 114 return false; 115 case '=': // 结束符 116 return false; 117 default: 118 break; 119 } 120 return true; 121 } 122 123 private static boolean isNumber(String num){ 124 Matcher m1 = p1.matcher("123"); 125 return m1.matches(); 126 } 127 private static boolean isStandard(String numStr) { 128 if (numStr == null || numStr.isEmpty()) // 表达式不能为空 129 return false; 130 Stack<Character> stack = new Stack<Character>(); // 用来保存括号,检查左右括号是否匹配 131 boolean b = false; // 用来标记'='符号是否存在多个 132 for (int i = 0; i < numStr.length(); i++) { 133 char n = numStr.charAt(i); 134 // 判断字符是否合法 135 if (!(isNumber(n+"") || "(".equals(n + "") || ")".equals(n + "") 136 || "+".equals(n + "") || "-".equals(n + "") 137 || "*".equals(n + "") || "/".equals(n + "") 138 || "=".equals(n + ""))) { 139 return false; 140 } 141 // 将左括号压栈,用来给后面的右括号进行匹配 142 if ("(".equals(n + "")) { 143 stack.push(n); 144 } 145 if (")".equals(n + "")) { // 匹配括号 146 if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配 147 return false; 148 } 149 // 检查是否有多个'='号 150 if ("=".equals(n + "")) { 151 if (b) 152 return false; 153 b = true; 154 } 155 } 156 // 可能会有缺少右括号的情况 157 if (!stack.isEmpty()) 158 return false; 159 return true; 160 } 161 162 }