四则运算Java实现

四则运算中缀转后缀方法计算(推荐)
四则运算递归计算(不推荐,()层数越多就会越慢)

首先做好准备工作
1、二个数字计算方法体
2、运算符优先级的设定
3、打散字符串获得数字和字符的List集合(注意负值的分割点)
@Component
public class Common {
    /**
     * 两位数double计算(或者用BigDecimal计算)
     * @param a1
     * @param a2
     * @param operator
     * @return
     * @throws Exception
     */
    protected static double doubleCal(double a1, double a2, char operator) throws Exception{
        switch (operator) {
            case '+':
                return a1 + a2;
            case '-':
                return a1 - a2;
            case '*':
                return a1 * a2;
            case '/':
                return a1 / a2;
            default:
                break;
        }
        throw new Exception("数据异常");
    }

    /**
     * 获得优先级
     *
     * @param s
     * @return
     * @throws Exception
     */
    protected static int getPriority(String s) throws Exception{
        // "null" 栈顶若为空,假设优先级为0, "(" 优先级设为1, "+-" 优先级设为2, "*/" 优先级设为3
        if(s==null){
            return 0;
        }
        switch(s) {
            case "(":return 1;
            case "+":
            case "-":return 2;
            case "*":
            case "/":return 3;
            default:break;
        }
        throw new Exception("数据异常");
    }

    /**
     * 打散字符串获得数字和符号
     *
     * @param str
     * @return
     */
    protected static List<String> getList(String str){
        char[] chars = str.toCharArray();
        //标志
        String sign = "";
        //缓存正负号
        String redis = "";
        List<String> list = new ArrayList<>();
        StringBuilder temporary = new StringBuilder();
        for (char c : chars) {
            if (c >= '0' && c <= '9') {
                //是数字
                if(StringUtil.isNotEmpty(redis)){
                    //有缓存符号数字加入正负号
                    temporary.append(redis + c);
                    redis = "";
                }else{
                    temporary.append(c);
                }
                sign = "";
            } else if (c == '.') {
                //多小数点入参校验
                if (temporary.indexOf(".") > 0) {
                    System.out.println("入参错误");
                }
                temporary.append(c);
                sign = "";
            } else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {
                //遇到符号从新记录数字,原数字加入list集合分开字符串
                if (temporary.length() > 0) {
                    list.add(temporary.toString());
                    temporary.setLength(0);
                }
                if(StringUtil.isNotEmpty(sign) && !sign.equals(")") && (c == '+' || c == '-')){
                    redis = c + "";
                    sign = "";
                }else{
                    list.add(c + "");
                }
                //记录标志
                sign = c + "";
            } else if (c == ' ') {
                //跳过空格
                continue;
            } else {
                System.out.println("入参错误");
            }
        }
        //最后一组数字
        if (temporary.length() > 0) {
            list.add(temporary.toString());
        }
        return list;
    }
    
    /**
     * 去除只包含一组数字的()
     * @param list
     * @return
     */
    public static List<String> getList(List<String> list){
        int a = 0;
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            if (s.equals("(")) {
                a = i;
            }
            if (s.equals(")")) {
                if ((i - 2) == a) {
                    list.remove(i);
                    list.remove(a);
                }
            }
        }
        return list;
    }
}
/**
 * 四则运算后缀方法计算
 */
public class Test1 {
    public static void main(String[] args) throws Exception {
        String str = "2*2*((2*6)+(11+4))-6*-1";
        List<String> list = Common.getList(str);
        String sufExpr = getSufExpr(list);
        String result = getResult(sufExpr);
        System.out.println(result);
    }

    /**
     * 中缀转后缀
     * @param list
     * @return
     * @throws Exception
     */
    private static String getSufExpr(List<String> list) throws Exception {
        /*返回结果字符串*/
        StringBuilder sufExpr = new StringBuilder();
        /*盛放运算符的栈*/
        Stack<String> operator = new Stack<>();
        /*在栈顶压入一个null假设优先级为0*/
        operator.push(null);
        String topItem;
        for (String temp :list) {
            /*运算符*/
            if (temp.matches("[+\\-*/()]")) {
                /*遇到左括号直接压栈*/
                if (temp.equals("(")) {
                    operator.push(temp);
                    /*遇到右括号弹栈输出直到弹出左括号(不包括左括号)*/
                } else if (temp.equals(")")) {
                    while (!(topItem = operator.pop()).equals("(")) {
                        sufExpr.append(topItem+" ");
                    }
                } else {
                    /*遇到运算符比较栈顶符号,若该运算符优先级大于栈顶直接压栈。若小于栈顶弹栈输出直到大于栈顶,然后将改运算符压栈*/
                    while(Common.getPriority(temp) <= Common.getPriority(operator.peek())) {
                        sufExpr.append(operator.pop()+" ");
                    }
                    operator.push(temp);
                }
            }else {
                /*遇到数字直接输出*/
                sufExpr.append(temp+" ");
            }
        }
        while(null != (topItem = operator.pop())) {
            sufExpr.append(topItem+" ");
        }
        return sufExpr.toString();
    }

    /**
     * 解析后缀表达式
     * @param sufExpr
     * @return
     * @throws Exception
     */
    public static String getResult(String sufExpr) throws Exception {
        /*盛放数字栈*/
        Stack<Double> number = new Stack<>();
        /*这个正则匹配每个数字和符号*/
        final Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?|[+\\-*/]");
        Matcher m = pattern.matcher(sufExpr);
        while (m.find()) {
            String temp = m.group();
            if (temp.matches("[+\\-*/]")) {
                /*遇到运算符,将最后两个数字取出,进行该运算,将结果再放入容器*/
                double a1 = number.pop();
                double a2 = number.pop();
                double res = Common.doubleCal(a2, a1, temp.charAt(0));
                number.push(res);
            } else {
                /*遇到数字直接放入容器*/
                number.push(Double.valueOf(temp));
            }
        }
        return number.pop() + "";
    }
}
/**
 * 四则运算递归方法计算
 */
public class Test2 {
    public static void main(String[] args) throws Exception {
        String str = "2*2*((2*6)+(11+4))-6*-1";
        List<String> list = Common.getList(str);
        String result = getResult(list).get(0);
        System.out.println(result);
    }

    private static List<String> getResult(List<String> list) throws Exception {
        //缓存数字
        String num = "";
        //缓存符号
        String redis = "";
        List<String> list1 = new ArrayList<>();
        //计算乘除
        String symbol = "[*/]";
        Compute compute1 = new Compute(list, num, redis, list1, symbol).invoke();
        num = compute1.getNum();
        redis = compute1.getRedis();
        //处理尾数
        TailNum tailNum = null;
        tailNum = new TailNum(num, redis, list1).invoke();
        num = tailNum.getNum();
        redis = tailNum.getRedis();
        //去掉只有一组数字的()
        list1 = Common.getList(list1);
        List<String> list2 = new ArrayList<>();
        //计算加减
        symbol = "[+\\-]";
        Compute compute2 = new Compute(list1, num, redis, list2, symbol).invoke();
        num = compute2.getNum();
        redis = compute2.getRedis();
        //处理尾数
        tailNum = new TailNum(num, redis, list2).invoke();
        num = tailNum.getNum();
        redis = tailNum.getRedis();
        //去掉只有一组数字的()
        list2 = Common.getList(list2);
        if(list2.size()>1){
            //不是一个数字递归计算
            list2 = getResult(list2);
        }
        return list2;
    }

    /**
     * 尾数加入集合并清除临时数据
     */
    private static class TailNum {
        private String num;
        private String redis;
        private List<String> list1;

        public TailNum(String num, String redis, List<String> list1) {
            this.num = num;
            this.redis = redis;
            this.list1 = list1;
        }

        public String getNum() {
            return num;
        }

        public String getRedis() {
            return redis;
        }

        public TailNum invoke() {
            if(!StringUtil.isEmpty(redis)){
                list1.add(redis + "");
                redis = "";
            }
            if(!StringUtil.isEmpty(num)){
                list1.add(num + "");
                num = "";
            }
            return this;
        }
    }

    /**
     * 返回结果存入缓存
     */
    private static class Compute {
        private List<String> list;
        private String num;
        private String redis;
        private List<String> list1;
        private String str;

        public Compute(List<String> list, String num, String redis, List<String> list1, String str) {
            this.list = list;
            this.num = num;
            this.redis = redis;
            this.list1 = list1;
            this.str = str;
        }

        public String getNum() {
            return num;
        }

        public String getRedis() {
            return redis;
        }

        public Compute invoke() throws Exception {
            for (String temp :list) {
                if (temp.matches("[+\\-*/()]")) {
                    /*运算符*/
                    Symbol symbol = new Symbol(num, redis, list1, temp).invoke(str);
                    num = symbol.getNum();
                    redis = symbol.getRedis();
                }else{
                    /*数字*/
                    Num num1 = new Num(num, redis, temp).invoke();
                    num = num1.getNum();
                    redis = num1.getRedis();
                }
            }
            return this;
        }
    }

    /**
     * 符号处理
     */
    protected static class Symbol {
        private String num;
        private String redis;
        private List<String> list;
        private String temp;

        public Symbol(String num, String redis, List<String> list, String temp) {
            this.num = num;
            this.redis = redis;
            this.list = list;
            this.temp = temp;
        }

        public String getNum() {
            return num;
        }

        public String getRedis() {
            return redis;
        }

        public Symbol invoke(String symbol) {
            if(temp.matches(symbol)){
                if(StringUtil.isEmpty(redis)){
                    redis = temp;
                }
            }else{
                if(!StringUtil.isEmpty(num)){
                    list.add(num + "");
                }
                if(!StringUtil.isEmpty(redis)){
                    list.add(redis + "");
                }
                list.add(temp + "");
                num = "";
                redis = "";
            }
            return this;
        }
    }

    /**
     * 数字处理
     */
    protected static class Num {
        private String num;
        private String redis;
        private String temp;

        public Num(String num, String redis, String temp) {
            this.num = num;
            this.redis = redis;
            this.temp = temp;
        }

        public String getNum() {
            return num;
        }

        public String getRedis() {
            return redis;
        }

        public Num invoke() throws Exception {
            //缓存数字空则赋值,非空有缓存符号同时存在则计算结果并加入缓存,以供下一组数字计算用
            if(StringUtil.isEmpty(num)){
                num = temp;
            }else if(!StringUtil.isEmpty(redis)){
                double a1 = Double.valueOf(num);
                double a2 = Double.valueOf(temp);
                double res = Common.doubleCal(a2, a1, redis.charAt(0));
                num = res+"";
                redis = "";
            }
            return this;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值