(算法)java完成解析数学算式(计算器)一 —— 递归、正则直接遍历字符串解析

一、程序要求

解析一般数学算式,实现简单的带括号的加减乘除运算。

二、基本思路

先从我们人的角度,考虑平时在计算一个式子的思路,任意假设一个的数学表达式-3.5*(4.5-(4+(-1-1/2)))

  • 1、计算最里面的括号(最后一个左括号)里的表达式(-1-1/2)
  • 2、计算除法1/2,将括号内容变为(-1-0.5)
  • 3、计算减法,得出括号结果-1.5
  • 4、用该结果将括号替换,表达式变为-3.5*(4.5-(4+-1.5))
  • 5、重复1-4步,去掉剩下的两个括号,将表达式变为-3.5*2
  • 6、算一步乘法,得-7,除了首位正负号外,不含其它符号,即运算结束,-7为运算结果

简单总结,即先去括号至无括号,再去乘除至无乘除,最后去加减至无加减,以此思路编写程序如下,结合注释分析具体步骤:

三、代码

先写一个最基本的两位数四则运算方法,比较简单,没有写注释:

public 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("illegal operator!");
    }

解析运算表达式的方法:

    public static String getResult(String str) throws NumberFormatException, Exception {

        //处理一下计算过程中出现的--情况,首位--直接去掉,中间--变为+
        str = str.startsWith("--") ? str.substring(2) : str;
        str = str.replaceAll("--", "+");
        str = str.replaceAll("\\+-", "-");
        System.out.println("新表达式:"+str);
        if (str.matches("-{0,1}[0-9]+([.][0-9]+){0,1}"))//不存在运算符了,即递归结束,这里的正则为匹配所有的正负整数及小数
            return str;

        /*表示每次递归计算完一步后的表达式*/
        String newExpr = null;
        // 第一步:去括号至无括号
        if (str.contains("(")) {
            /*最后一个左括号的索引值*/
            int lIndex = str.lastIndexOf("(");
            /*该左括号对应的右括号的索引*/
            int rIndex = str.indexOf(")", lIndex); 
            /*括号中的字表达式*/
            String subExpr = str.substring(lIndex + 1, rIndex);
            System.out.println("准备括号:("+subExpr+")");
            newExpr = str.substring(0, lIndex) + getResult(subExpr) //调用本身,计算括号中表达式结果
                    + str.substring(rIndex + 1);
            return getResult(newExpr);
        }

        // 第二步:去乘除至无乘除
        if (str.contains("*") || str.contains("/")) {
            /*该正则表示匹配一个乘除运算,如1.2*3  1.2/3  1.2*-2 等*/
            Pattern p = Pattern.compile("[0-9]+([.][0-9]+){0,1}[*/]-{0,1}[0-9]+([.][0-9]+){0,1}");
            Matcher m = p.matcher(str);
            if (m.find()) {
                /*第一个乘除表达式*/
                String temp = m.group();
                System.out.println("计算乘除:"+temp);
                String[] a = temp.split("[*/]");
                newExpr = str.substring(0, m.start())
                        + doubleCal(Double.valueOf(a[0]), Double.valueOf(a[1]), temp.charAt(a[0].length()))
                        + str.substring(m.end());
            }
            return getResult(newExpr);
        }

        // 第三步:去加减至无加减
        if (str.contains("+") || str.contains("-")) {
            /*该正则表示匹配一个乘除运算,如1.2+3  1.2-3  1.2--2  1.2+-2等*/
            Pattern p = Pattern.compile("-{0,1}[0-9]+([.][0-9]+){0,1}[+-][0-9]+([.][0-9]+){0,1}");
            Matcher m = p.matcher(str);
            if (m.find()) {
                /*第一个加减表达式*/
                String temp = m.group();
                System.out.println("计算加减:"+temp);
                String[] a = temp.split("\\b[+-]", 2);
                newExpr = str.substring(0, m.start())
                        + doubleCal(Double.valueOf(a[0]), Double.valueOf(a[1]), temp.charAt(a[0].length()))
                        + str.substring(m.end());
            }
            return getResult(newExpr);
        }

        throw new Exception("Calculation error");
    }

主方法:

public static void main(String[] args) throws Exception {
        String str = "-3.5*(4.5-(4+(-1-1/2)))";
        System.out.println("开始计算表达式:"+str);
        System.out.println("结果为:"+getResult(str));
    }

四、运行结果

这里写图片描述

五、分析

这种方法以我们平时计算的思路入手,思路较为清晰,代码简略,但直接遍历拼接字符串,代码并不好读,多次递归效率也必然较低。引入第二种思路,采用java的容器进一步优化算法及代码。

猜你喜欢

转载自blog.csdn.net/qq_37969433/article/details/81174046