- 问题描述
- 实现一个计算器,输入:运算表达式的字符串,输出:计算结果
- 能够进行运算表达式的正确性校验
- 能够计算小数
- 源码 : Calculate
- 值的你关注并提升你薪资待遇的面试算法:开源数据结构和算法实践
- 测试案例及注意事项
- 校验失败的统一输出值为: Integer.MIN_VALUE
- 对于循环小数,需要截取为字符串来处理:DecimalFormat("#.00000");
String calNum01 = "(2+3*5)*(";
double ans01 = Integer.MIN_VALUE;
String calNum011 = "";
double ans011 = Integer.MIN_VALUE;
String calNum012 = null;
double ans012 = Integer.MIN_VALUE;
String calNum02 = "(5/3*( 3+3)";
double ans02 = Integer.MIN_VALUE;
String calNum03 = "(4*6 )+(2+/ 3+ 4 -5)";
double ans03 = Integer.MIN_VALUE;
String calNum04 = "2*(.23+4)";
double ans04 = Integer.MIN_VALUE;
String calNum042 = "2*(1.23+0 .0.4)";
double ans042 = Integer.MIN_VALUE;
String calNum043 = "2*(1.2 .3+0 4)";
double ans043 = Integer.MIN_VALUE;
String calNum044 = "2*(=1.23+04)";
double ans044 = Integer.MIN_VALUE;
String calNum045 = "2*(1.2d3+0j4)";
double ans045 = Integer.MIN_VALUE;
String calNum05 = "2 + 3 * 6 / 2 + 8";
double ans05 = 19;
String calNum051 = "2 + 03 * 6 / 002 + 8";
double ans051 = 19;
String calNum06 = "2.1 5+3.45* 6/2+ 8.1";
double ans06 = 20.6;
String calNum07 = "(2.15+3.451 77)*6/2+ 8.1-(2.1 7 *45-2*3)";
double ans07 = -66.74469;
String calNum08 = "23.6 7+12.41*(2.3 +5.90)+(12/2 + 3.41)*(8 /4+3-6/2)";
double ans08 = 144.252;
String calNum09 = "102 + 3 * 6 / 2 + 10008";
double ans09 = 10119;
- 设计思路
- 第一部分,校验并处理输入的计算式
- 第二部分,中缀表达式转化为后缀表达式
- 第三部分,计算后缀表达式,并返回运算结果
代码展示
public boolean check(String s) {
if (s == null || s.length() == 0) {
return false;
}
s = s.replaceAll("\\s*", "");
String pattern = "([+\\-*/()\\d.]?)*";
if (!s.matches(pattern)) {
return false;
}
if (!effectBrackets.EffectBracketsbyStack(s)) {
return false;
}
List<Character> listChar = Stream.of('+','-','*','/').collect(Collectors.toList());
boolean flagChar = false;
for (int i = 0; i < s.length(); i++) {
if (flagChar && listChar.contains(s.charAt(i))) {
return false;
}
if(s.charAt(i)=='(' && listChar.contains(s.charAt(i+1))){
return false;
}
if (flagChar && ")".equals(String.valueOf(s.charAt(i)))) {
return false;
}
flagChar = listChar.contains(s.charAt(i));
}
return true;
}
public List<String> string2list(String s) {
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (isDigital(c)) {
sb.append(c);
}
if (isOption(c)) {
if (sb.length() != 0) {
list.add(sb.toString());
sb.delete(0, sb.length());
}
list.add(String.valueOf(c));
}
}
if (sb.length() != 0) {
list.add(sb.toString());
sb.delete(0, sb.length());
}
return list;
}
private List<String> infix2suffix(List<String> infixList) {
List<String> suffixList = new ArrayList<>();
Stack<String> stackTemp = new Stack<>();
for (String s : infixList) {
if ("(".equals(s) || "*".equals(s) || "/".equals(s)) {
stackTemp.push(s);
} else if ("+".equals(s) || "-".equals(s)) {
if (!stackTemp.empty()) {
while (!stackTemp.peek().equals("(")) {
suffixList.add(stackTemp.pop());
if (stackTemp.empty()) {
break;
}
}
}
stackTemp.add(s);
} else if (")".equals(s)) {
while (!stackTemp.empty() && !stackTemp.peek().equals("(")) {
suffixList.add(stackTemp.pop());
}
stackTemp.pop();
} else {
suffixList.add(s);
}
}
while (!stackTemp.empty()) {
suffixList.add(stackTemp.pop());
}
return suffixList;
}
private double count(List<String> suffixList) {
Stack<Double> stack = new Stack();
for (String temp : suffixList) {
double value;
if (!isOption(temp)) {
if (temp.contains(".")) {
String[] de = temp.split("\\.");
if (de.length > 2 || de[0] == null || de[0].length() == 0) {
return Integer.MIN_VALUE;
}
int v1 = Integer.parseInt(de[0]);
value = v1 + Double.parseDouble(de[1]) / Math.pow(10, de[1].length());
} else {
value = Integer.parseInt(temp);
}
stack.push(value);
} else {
double a1 = stack.pop();
double a2 = stack.pop();
double value1 = 0;
switch (temp) {
case "+":
value1 = a1 + a2;
break;
case "-":
value1 = a2 - a1;
break;
case "*":
value1 = a1 * a2;
break;
case "/":
value1 = a2 / a1;
break;
}
stack.push(value1);
}
}
return stack.pop();
}
private boolean isDigital(char c) {
return (c >= '0' && c <= '9' || c == '.');
}
Character[] c1 = {'+', '-', '*', '/', '(', ')'};
String[] s1 = {"+", "-", "*", "/", "(", ")"};
private boolean isOption(char c) {
long count = Arrays.stream(c1).filter(x -> (x == c)).count();
return count != 0;
}
private boolean isOption(String c) {
long count = Arrays.stream(s1).filter(x -> x.equals(c)).count();
return count != 0;
}