归子莫的博客

「笔杆揭不起,绘不出青烟别春泥 ————归子莫」

完整逆波兰计算器(Java)

博客说明

文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!

功能

支持 + - * / ( )
多位数,支持小数,
兼容处理, 过滤任何空白字符,包括空格、制表符、换页符

基本思路

中缀表达式转后缀表达式

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package stack;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.Collections;
import java.util.regex.Pattern;

public class ReversePolishMultiCalc {
//匹配运算符
static final String SYMBOL = "\\+|-|\\*|/|\\(|\\)";

static final String LEFT = "(";
static final String RIGHT = ")";
static final String ADD = "+";
static final String MINUS = "-";
static final String TIMES = "*";
static final String DIVISION = "/";

//优先级
static final int LEVEL_01 = 1;
static final int LEVEL_02 = 2;
static final int LEVEL_HIGH = Integer.MAX_VALUE;

static Stack<String> stack = new Stack<>();
static List<String> data = Collections.synchronizedList(new ArrayList<String>());

//去除所有空白符号
public static String replaceAllBlank(String s) {
return s.replaceAll("\\s+", "");
}

//判断是否为数字
public static boolean isNumber(String s) {
Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
return pattern.matcher(s).matches();
}

//判断是否是运算符
public static boolean isSymbol(String s) {
return s.matches(SYMBOL);
}

//匹配运算优先级
public static int calcLevel(String s) {
if ("+".equals(s) || "-".equals(s)) {
return LEVEL_01;
} else if ("*".equals(s) || "/".equals(s)) {
return LEVEL_02;
}
return LEVEL_HIGH;
}

//匹配
public static List<String> doMatch(String s) throws Exception {
if (s == null || "".equals(s.trim())) throw new RuntimeException("data is empty");
if (!isNumber(s.charAt(0) + "")) throw new RuntimeException("data illeagle,start not with a number");
s = replaceAllBlank(s);

String each;
int start = 0;

for (int i = 0; i < s.length(); i++) {
if (isSymbol(s.charAt(i) + "")) {
each = s.charAt(i) + "";
if (stack.isEmpty() || LEFT.equals(each) || ((calcLevel(each) > calcLevel(stack.peek())) && calcLevel(each) < LEVEL_HIGH)) {
stack.push(each);
} else if (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())) {
while (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())) {
if (calcLevel(stack.peek()) == LEVEL_HIGH) {
break;
}
data.add(stack.pop());
}
stack.push(each);
} else if (RIGHT.equals(each)) {
while (!stack.isEmpty() && LEVEL_HIGH >= calcLevel(stack.peek())) {
if (LEVEL_HIGH == calcLevel(stack.peek())) {
stack.pop();
break;
}
data.add(stack.pop());
}
}
start = i;
} else if (i == s.length() - 1 || isSymbol(s.charAt(i + 1) + "")) {
each = start == 0 ? s.substring(start, i + 1) : s.substring(start + 1, i + 1);
if (isNumber(each)) {
data.add(each);
continue;
}
throw new RuntimeException("data not match number");
}
}
Collections.reverse(stack);
data.addAll(new ArrayList<>(stack));
System.out.println(data);
return data;
}

//计算结果
public static Double doCalc(List<String> list){
Double d = 0d;
if(list == null || list.isEmpty()){
return null;
}
if(list.size() == 1){
System.out.println(list);
d = Double.valueOf(list.get(0));
return d;
}
ArrayList<String> list1 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list1.add(list.get(i));
if(isSymbol(list.get(i))){
Double d1 = doTheMath(list.get(i-2),list.get(i-1),list.get(i));
list1.remove(i);
list1.remove(i-1);
list1.set(i-2,d1+"");
list1.addAll(list.subList(i+1,list.size()));
break;
}
}
doCalc(list1);
return d;
}

//运算
public static Double doTheMath(String s1,String s2,String symbol){
Double result;
switch (symbol){
case ADD:
result = Double.valueOf(s1) + Double.valueOf(s2);
break;
case MINUS:
result = Double.valueOf(s1) - Double.valueOf(s2);
break;
case TIMES:
result = Double.valueOf(s1) * Double.valueOf(s2);
break;
case DIVISION:
result = Double.valueOf(s1) / Double.valueOf(s2);
break;
default:
result = null;
}
return result;
}

public static void main(String[] args) {
String math = "12.8 + (2-3.55)*4+10/5.0";
try{
doCalc(doMatch(math));
}catch (Exception e){
e.printStackTrace();
}
}

}

结果

image-20200625174138211

感谢

尚硅谷

万能的网络

以及勤劳的自己

评论