逆波兰计算器完整版
完整版的逆波兰计算器,功能包括:
(1)支持+,-,*,/,()
(2)支持多位数,支持小数
(3)兼容处理,过滤任何空白字符,包括空格、制表符,换页符
代码实现:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 import java.util.Stack; 5 import java.util.regex.Pattern; 6
7 public class ReversePolishMultiCalc { 8
9 /**
10 * 匹配 + - * / ( ) 运算符 11 */
12 static final String SYMBOL = "\\+|-|\\*|/|\\(|\\)"; 13
14 static final String LEFT = "("; 15 static final String RIGHT = ")"; 16 static final String ADD = "+"; 17 static final String MINUS= "-"; 18 static final String TIMES = "*"; 19 static final String DIVISION = "/"; 20
21 /**
22 * 加減 + - 23 */
24 static final int LEVEL_01 = 1; 25 /**
26 * 乘除 * / 27 */
28 static final int LEVEL_02 = 2; 29
30 /**
31 * 括号 32 */
33 static final int LEVEL_HIGH = Integer.MAX_VALUE; 34
35
36 static Stack<String> stack = new Stack<>(); 37 static List<String> data = Collections.synchronizedList(new ArrayList<String>()); 38
39 /**
40 * 去除所有空白符 41 * @param s 42 * @return
43 */
44 public static String replaceAllBlank(String s ){ 45 // \\s+ 匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[ \f\n\r\t\v]
46 return s.replaceAll("\\s+",""); 47 } 48
49 /**
50 * 判断是不是数字 int double long float 51 * @param s 52 * @return
53 */
54 public static boolean isNumber(String s){ 55 Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$"); 56 return pattern.matcher(s).matches(); 57 } 58
59 /**
60 * 判断是不是运算符 61 * @param s 62 * @return
63 */
64 public static boolean isSymbol(String s){ 65 return s.matches(SYMBOL); 66 } 67
68 /**
69 * 匹配运算等级 70 * @param s 71 * @return
72 */
73 public static int calcLevel(String s){ 74 if("+".equals(s) || "-".equals(s)){ 75 return LEVEL_01; 76 } else if("*".equals(s) || "/".equals(s)){ 77 return LEVEL_02; 78 } 79 return LEVEL_HIGH; 80 } 81
82 /**
83 * 匹配 84 * @param s 85 * @throws Exception 86 */
87 public static List<String> doMatch (String s) throws Exception{ 88 if(s == null || "".equals(s.trim())) throw new RuntimeException("data is empty"); 89 if(!isNumber(s.charAt(0)+"")) throw new RuntimeException("data illeagle,start not with a number"); 90
91 s = replaceAllBlank(s); 92
93 String each; 94 int start = 0; 95
96 for (int i = 0; i < s.length(); i++) { 97 if(isSymbol(s.charAt(i)+"")){ 98 each = s.charAt(i)+""; 99 //栈为空,(操作符,或者 操作符优先级大于栈顶优先级 && 操作符优先级不是( )的优先级 及是 ) 不能直接入栈
100 if(stack.isEmpty() || LEFT.equals(each) 101 || ((calcLevel(each) > calcLevel(stack.peek())) && calcLevel(each) < LEVEL_HIGH)){ 102 stack.push(each); 103 }else if( !stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())){ 104 //栈非空,操作符优先级小于等于栈顶优先级时出栈入列,直到栈为空,或者遇到了(,最后操作符入栈
105 while (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek()) ){ 106 if(calcLevel(stack.peek()) == LEVEL_HIGH){ 107 break; 108 } 109 data.add(stack.pop()); 110 } 111 stack.push(each); 112 }else if(RIGHT.equals(each)){ 113 // ) 操作符,依次出栈入列直到空栈或者遇到了第一个)操作符,此时)出栈
114 while (!stack.isEmpty() && LEVEL_HIGH >= calcLevel(stack.peek())){ 115 if(LEVEL_HIGH == calcLevel(stack.peek())){ 116 stack.pop(); 117 break; 118 } 119 data.add(stack.pop()); 120 } 121 } 122 start = i ; //前一个运算符的位置
123 }else if( i == s.length()-1 || isSymbol(s.charAt(i+1)+"") ){ 124 each = start == 0 ? s.substring(start,i+1) : s.substring(start+1,i+1); 125 if(isNumber(each)) { 126 data.add(each); 127 continue; 128 } 129 throw new RuntimeException("data not match number"); 130 } 131 } 132 //如果栈里还有元素,此时元素需要依次出栈入列,可以想象栈里剩下栈顶为/,栈底为+,应该依次出栈入列,可以直接翻转整个stack 添加到队列
133 Collections.reverse(stack); 134 data.addAll(new ArrayList<>(stack)); 135
136 System.out.println(data); 137 return data; 138 } 139
140 /**
141 * 算出结果 142 * @param list 143 * @return
144 */
145 public static Double doCalc(List<String> list){ 146 Double d = 0d; 147 if(list == null || list.isEmpty()){ 148 return null; 149 } 150 if (list.size() == 1){ 151 System.out.println(list); 152 d = Double.valueOf(list.get(0)); 153 return d; 154 } 155 ArrayList<String> list1 = new ArrayList<>(); 156 for (int i = 0; i < list.size(); i++) { 157 list1.add(list.get(i)); 158 if(isSymbol(list.get(i))){ 159 Double d1 = doTheMath(list.get(i - 2), list.get(i - 1), list.get(i)); 160 list1.remove(i); 161 list1.remove(i-1); 162 list1.set(i-2,d1+""); 163 list1.addAll(list.subList(i+1,list.size())); 164 break; 165 } 166 } 167 doCalc(list1); 168 return d; 169 } 170
171 /**
172 * 运算 173 * @param s1 174 * @param s2 175 * @param symbol 176 * @return
177 */
178 public static Double doTheMath(String s1,String s2,String symbol){ 179 Double result ; 180 switch (symbol){ 181 case ADD : result = Double.valueOf(s1) + Double.valueOf(s2); break; 182 case MINUS : result = Double.valueOf(s1) - Double.valueOf(s2); break; 183 case TIMES : result = Double.valueOf(s1) * Double.valueOf(s2); break; 184 case DIVISION : result = Double.valueOf(s1) / Double.valueOf(s2); break; 185 default : result = null; 186 } 187 return result; 188
189 } 190
191 public static void main(String[] args) { 192 //String math = "9+(3-1)*3+10/2";
193 String math = "12.8 + (2 - 3.55)*4+10/5.0"; 194 try { 195 doCalc(doMatch(math)); 196 } catch (Exception e) { 197 e.printStackTrace(); 198 } 199 } 200
201 }