可以进行浮点数运算的计算器

  • 问题描述
    • 实现一个计算器,输入:运算表达式的字符串,输出:计算结果
    • 能够进行运算表达式的正确性校验
    • 能够计算小数
  • 源码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;
    }
    //1、将string数据去空格  :s.replaceAll(" ","");
    s = s.replaceAll("\\s*", "");
    //2、是否仅含数字、字符(+、-、*、/、(、))、小数点
    String pattern = "([+\\-*/()\\d.]?)*";
    if (!s.matches(pattern)) {
        return false;
    }
    //3、判断括号是否符合标准
    if (!effectBrackets.EffectBracketsbyStack(s)) {
        return false;
    }
    //4、判断运算符是否符合标准
    /*List<Character> listChar = new ArrayList() {{
        add('+');
        add('-');
        add('*');
        add('/');
    }};*/
    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;
        }
        //出现( + 运算符,经过前面的括号匹配,所以此处的 i 不可能是最后一位,可以放心使用i+1
        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));
    }

    //5、判断数字是否标准
    //在 Calculate 的 count 中做过了

    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)) {//右括号出栈
            //如果数据可信,不需要加 !stackTemp.empty()
            while (!stackTemp.empty() && !stackTemp.peek().equals("(")) {
                suffixList.add(stackTemp.pop());
            }
            stackTemp.pop();
        } else {
            //纯数字 加入
            suffixList.add(s);
        }
    }
    //注意:兜底stack中的数据
    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;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值