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 }
java实现的带括号的计算器
点赞
收藏