1 1 import java.math.BigDecimal; 2 2 import java.util.ArrayList; 3 3 import java.util.List; 4 4 import java.util.Stack; 5 5 import java.util.regex.Matcher; 6 6 import java.util.regex.Pattern; 7 7 8 8 9 9 public class Calu { 10 10 private static List<String> sysboList=new ArrayList<String>(){{ 11 11 this.add("+"); 12 12 this.add("-"); 13 13 this.add("*"); 14 14 this.add("/"); 15 15 this.add("="); 16 16 }}; 17 17 private static Pattern p1 = Pattern.compile("(^[0-9]{1,9}[.][0-9]{1,2}$)|(^[0-9]{1,11}$)"); 18 18 19 19 public static void main(String[] args) { 20 20 String numstr="(2+2*(1+2))*3/2"; 21 21 System.out.println(result(numstr)); 22 22 } 23 23 24 24 public static BigDecimal result(String numstr){ 25 25 //先把括号中的值给算出来然后替换,找的括号是最小范围的 26 26 //最后一个'('出现的位置 到 第一个')'出现的位置 27 27 StringBuffer sb=new StringBuffer(numstr); 28 28 if(isStandard(sb.toString())){ 29 29 String rs=bracketsString(sb); 30 30 while(rs!=null){ 31 31 BigDecimal calBracketsValue = calBracketsValue(rs+"="); 32 32 sb.replace(sb.indexOf("@"), sb.indexOf("@")+1, calBracketsValue.toString()); 33 33 System.out.println(sb); 34 34 rs=bracketsString(sb); 35 35 } 36 36 return calBracketsValue(sb.toString()+"="); 37 37 } 38 38 return new BigDecimal("0"); 39 39 } 40 40 41 41 public static String bracketsString(StringBuffer str){ 42 42 int leftBracketsPoint=str.lastIndexOf("("); 43 43 int rightBracketsPoint=str.indexOf(")"); 44 44 if(leftBracketsPoint==-1 || rightBracketsPoint==-1){ 45 45 return null; 46 46 } 47 47 String res= str.substring(leftBracketsPoint+1,rightBracketsPoint); 48 48 str.replace(leftBracketsPoint, rightBracketsPoint+1, "@"); 49 49 return res; 50 50 } 51 51 52 52 //计算括号中的表达式的值 53 53 public static BigDecimal calBracketsValue(String numStr){ 54 54 Stack<BigDecimal> numStack=new Stack<BigDecimal>();//数字栈 55 55 Stack<String> sysmboStack=new Stack<String>();//符号栈 56 56 int lastSysboPoint=0;//上一次非数字出现的位置 57 57 for(int i=0;i<numStr.length();i++){ 58 58 String ch=numStr.charAt(i)+""; 59 59 if(sysboList.contains(ch)){ 60 60 //开始计算入栈 61 61 //先把前面的数字入栈 1+1*1= 62 62 String num=numStr.substring(lastSysboPoint,i); 63 63 numStack.push(new BigDecimal(num)); 64 64 65 65 while(!sysmboStack.isEmpty() && !comparePri(ch.charAt(0),sysmboStack.peek().charAt(0))){//如果符号栈不为空,就把前一个符号拿出来和现在的符号做优先级对比 66 66 BigDecimal num2=numStack.pop(); 67 67 BigDecimal num1=numStack.pop(); 68 68 String sysboTemp=sysmboStack.pop(); 69 69 if(sysboTemp.equals("+")){ 70 70 numStack.push(num1.add(num2)); 71 71 }else if(sysboTemp.equals("-")){ 72 72 numStack.push(num1.subtract(num2)); 73 73 }else if(sysboTemp.equals("*")){ 74 74 numStack.push(num1.multiply(num2)); 75 75 }else if(sysboTemp.equals("/")){ 76 76 numStack.push(num1.divide(num2,10,BigDecimal.ROUND_HALF_DOWN)); 77 77 } 78 78 } 79 79 sysmboStack.push(ch); 80 80 lastSysboPoint=i+1; 81 81 } 82 82 } 83 83 84 84 return numStack.pop(); 85 85 } 86 86 87 87 88 88 89 89 private static boolean comparePri(char symbol,char top) { 90 90 if (top == '(') { 91 91 return true; 92 92 } 93 93 // 比较优先级 94 94 switch (symbol) { 95 95 case '(': // 优先级最高 96 96 return true; 97 97 case '*': { 98 98 if (top == '+' || top == '-') // 优先级比+和-高 99 99 return true; 100100 else 101101 return false; 102102 } 103103 case '/': { 104104 if (top == '+' || top == '-') // 优先级比+和-高 105105 return true; 106106 else 107107 return false; 108108 } 109109 case '+': 110110 return false; 111111 case '-': 112112 return false; 113113 case ')': // 优先级最低 114114 return false; 115115 case '=': // 结束符 116116 return false; 117117 default: 118118 break; 119119 } 120120 return true; 121121 } 122122 123123 private static boolean isNumber(String num){ 124124 Matcher m1 = p1.matcher("123"); 125125 return m1.matches(); 126126 } 127127 private static boolean isStandard(String numStr) { 128128 if (numStr == null || numStr.isEmpty()) // 表达式不能为空 129129 return false; 130130 Stack<Character> stack = new Stack<Character>(); // 用来保存括号,检查左右括号是否匹配 131131 boolean b = false; // 用来标记'='符号是否存在多个 132132 for (int i = 0; i < numStr.length(); i++) { 133133 char n = numStr.charAt(i); 134134 // 判断字符是否合法 135135 if (!(isNumber(n+"") || "(".equals(n + "") || ")".equals(n + "") 136136 || "+".equals(n + "") || "-".equals(n + "") 137137 || "*".equals(n + "") || "/".equals(n + "") 138138 || "=".equals(n + ""))) { 139139 return false; 140140 } 141141 // 将左括号压栈,用来给后面的右括号进行匹配 142142 if ("(".equals(n + "")) { 143143 stack.push(n); 144144 } 145145 if (")".equals(n + "")) { // 匹配括号 146146 if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配 147147 return false; 148148 } 149149 // 检查是否有多个'='号 150150 if ("=".equals(n + "")) { 151151 if (b) 152152 return false; 153153 b = true; 154154 } 155155 } 156156 // 可能会有缺少右括号的情况 157157 if (!stack.isEmpty()) 158158 return false; 159159 return true; 160160 } 161161 162162 }
java实现的带括号的计算器
Wesley13
2021-10-11
1118 1 0
点赞
收藏
评论区
加载中...