树莓派提升计划 Android应用科学计算器开发之中缀表达式计算

这篇博客详细介绍了如何使用基于堆栈的算法实现中缀表达式到后缀表达式的转换,并进行了后缀表达式的计算。文章中定义了一个Ele类来表示后缀表达式的元素,提供了isNum方法判断字符是否为数字,以及operate方法执行四则和指数运算。在转换过程中,通过两个栈和一个队列,遵循特定规则将中缀表达式转换为后缀表达式,最后对后缀表达式进行计算得出结果。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

        这篇研究BaseCalculator类中对中缀表达式的计算

        使用的是基于堆栈的算法,有一个元素类用于表示后缀表达式中的每一个元素

private class Ele {
        public boolean isNum;
        public double o;
        public char op;
        public Ele(double o,boolean isNum){
            this.isNum=isNum;
            this.o=o;
        }

        public Ele(char op,boolean isNum) {
            this.isNum = isNum;
            this.op = op;
        }
    }

用于进行后缀表达式计算。

        判断是否是数字

private boolean isNum(char c){
        return (c-'0'>=0&&c-'0'<=9)||c=='.';
    }

        operate方法提供简单的四则和E运算

private double operate(double a, char oper, double b) {
        switch (oper) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '×':
                return a * b;
            case '/':
                if (b == 0) {
                    return Double.MAX_VALUE; //处理异常
                }
                return a / b;
            case 'E':
                return Double.parseDouble(String.valueOf(a+"E"+(int)b));
            default:
                return 0;
        }
    }

        接下来就是关键的运算了

        先初始化一个队列和数字栈,字符栈

Stack<Character> operStack = new Stack<>();
Queue<Ele> eleQueue = new LinkedList<>();
Stack<Double> numStack = new Stack<>();

        中缀表达式转后缀表达式

  1. 初始化两个栈:运算符栈s1和储存后缀表达式的队列s2 从左至右扫描中缀表达式; 遇到操作数时,将其压入s2
  2. 遇到运算符时,比较其与s1栈顶运算符的优先级: 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
  3. 否则,若优先级比栈顶运算符的高,也将运算符压入s1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
  4. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)s1中新的栈顶运算符相比较; 遇到括号时:
  5. 如果是左括号“(”,则直接压入s1
  6. 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;
  7. 重复步骤25,直到表达式的最右边; s1中剩余的运算符依次弹出并压入s2
  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)
int firstIndex = 0;
            int i=0;
            while (i < math.length()) {
                char charOfMath = math.charAt(i);
                if (charOfMath == '(') {
                    operStack.push(charOfMath);
                    i++;
                } else if (charOfMath == ')') {
                    while (operStack.peek() != '(') {
                        eleQueue.offer(new Ele(operStack.pop(), false));
                    }
                    operStack.pop();
                    i++;
                }else if(isNum(charOfMath)){
                    firstIndex=i;
                    while (++i<math.length()&&isNum(math.charAt(i)));
                    double num;
                    try {
                        num = Double.parseDouble(math.substring(firstIndex, i));
                    } catch (NumberFormatException e) {
                        return Double.MAX_VALUE;
                    }
                    eleQueue.offer(new Ele(num,true));
                }else{
                    //说明-是单目运算符
                    if (charOfMath == '-') {
                        if (i == 0) {
                            firstIndex=0;
                            while (++i<math.length()&&isNum(math.charAt(i)));
                            double num;
                            try {
                                num = Double.parseDouble(math.substring(firstIndex, i));
                            } catch (NumberFormatException e) {
                                return Double.MAX_VALUE;
                            }
                            eleQueue.offer(new Ele(num,true));
                            continue;
                        } else if (math.charAt(i - 1)=='(') {
                            //表示这是一个单目运算符
                            firstIndex=i;
                            while (++i<math.length()&&isNum(math.charAt(i)));
                            double num;
                            try {
                                num = Double.parseDouble(math.substring(firstIndex, i));
                            } catch (NumberFormatException e) {
                                return Double.MAX_VALUE;
                            }
                            eleQueue.offer(new Ele(num,true));
                            continue;
                        }


                    }
                    while (operStack.size() >= 0) {
                        if (operStack.size() == 0 || operStack.peek() == '(') {
                            operStack.push(charOfMath);
                            break;
                        } else {
                            if (operMap.get(operStack.peek()) < operMap.get(charOfMath)) {
                                operStack.push(charOfMath);
                                break;
                            } else {
                                eleQueue.offer(new Ele(operStack.pop(), false));
                            }
                        }
                    }
                    i++;
                }
            }

            while (operStack.size()>0){
                eleQueue.offer(new Ele(operStack.pop(),false));
            }

        最后检查后缀表达式进行计算

        从左到右扫描后缀表达式,如果是操作数,就压入操作数栈s3,如果是操作符,就连续弹出两个操作数(注意:后弹出的为第一操作数,先弹出的为第二操作数),然后进行操作符的操作,将新生成的操作数压入栈中,反复直到后缀表达式扫面完毕,栈s3中只存在一个数,就是最终结果。

while (eleQueue.size() > 0) {
                if (eleQueue.element().isNum) {
                    numStack.push(eleQueue.poll().o);
                } else {
                    char op = eleQueue.poll().op;
                    double second= numStack.pop();
                    double first = numStack.pop();
                    numStack.push(operate(first, op, second));
                }
            }
            return numStack.peek();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值