对一个可进行带括号、加减乘除运算类的分析

 源程序来源于:http://bbs.tarena.com.cn/viewthread.php?tid=102826&extra=&page=1

这里主要对该程序的运行进行基本的分析,搞清楚其原理。因为我本人原来在参加面试的时候遇到过这样的问题,当时就没有答上来,有点后悔,所有这里补补。

这个程序主要采用的是将数进行压栈的方式,我们知道栈的方式是先进后出,一直遇到当前阶段优先级最高的才做运算,如这个表达式:"1+2*(3+4)",这里的数字栈和运算符分别变化如下:

栈数/符的推入就不例出来了,这里主要例当遇到最高级别的运算符的时候,如何进行运算的:

数字栈:1234

运算符栈:#+*(+

===========================

数字栈:127

运算符栈:#+*(

===========================

数字栈:127

运算符栈:#+*

===========================

数字栈:114

运算符栈:#+

===========================

数字栈:15

运算符栈:#

===========================

到这里根据条件就运算完了,就得到了我们想要的结果。源程序如下:

import java.util.Stack;
public class MyCal {
    // 运算符优先级比较函数
    static int co(char a, char b) {
        if (a == '+' || a == '-') {
            if (b == '+' || b == '-' || b == ')' || b == '#')
                return 1; // a>b
            return -1; // a<B a="=" 1; return ab
        }
        if (a == '(' || a == '#') {
            if (a == '(' && b == ')')
                return 0; // a==b
            else if (a == '(' && b == '#')
                return 2; // can't compare
            else if (a == '#' && b == ')')
                return 2;
            else if (a == '#' && b == '#')
                return 0;
            else
                return -1;
        }
        if (a == ')') {
            if (b == '(')
                return 2;
            else
                return 1;
        }
        return 0;
    }

    // 判断表达式中数字的函数
    boolean isnum(char ch) {
        if ((ch >= '0' && ch <= '9') || ch == '.')
            return true;
        return false;
    }

    // 判断表达式中运算符的函数
    static boolean issign(char ch) {
        if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || 
            ch == ')' || ch == '#')
            return true;
        return false;
    }

    // 计算最简表达式值的函数
    // a和b是操作数,s是运算符
    static double cal(double a, char s, double b) {
        if (s == '+')
            return a + b; // a+b返回a+b的值
        if (s == '-')
            return b - a; // 由于操作数出栈顺序是后进先出,所以减法和除法要、返回值表达式中要交换参数的顺序
        if (s == '*')
            return a * b; // a*b返回a*b的值
        if (s == '/')
            return b / a; // 同减法
        return 0;
    }

    // 计算整个表达式值的函数
    static double calculate(String s) {
        s += "#";
        int i = 0; // 表达式循环条件
        char c; // 表达式中的一个字符
        Stack
  
  
   
    num = new Stack
   
   
    
    (); // 操作数栈
        Stack
    
    
     
      op = new Stack
     
     
      
      (); // 操作符栈
        op.push('#'); // 表达式开始的标志
        c = s.substring(i, i + 1).charAt(0); // 取出表达式中的一位
        while (c != '#' || 
               op.peek().toString().charAt(0) != '#') // 没有取到表达式开始或结束的标志'#',就循环计算表达式的值
        {
            if (!issign(c)) // 取到的字符是数字,那么就要取出整个数字
            {
                int start = i;
                int end = 0;
                while (!issign(s.substring(i, i + 1).charAt(0)))
                    // 只要s[i]是数字,就表示一个数还没完
                    end = i++; // 循环条件自加
                double m = 
                    Double.parseDouble(s.substring(start, end + 1)); // 取出从i位开始的数字
                num.push(m); // 数字入栈
                c = s.substring(i, i + 1).charAt(0); // 下一个字符
            } else // 取到的字符是运算符
            {
                switch (co(op.peek(), c)) // 与栈中的运算符比较优先级
                {
                case -1: // 栈中运算符优先级小于当前运算符
                    op.push(c); // 运算符入栈
                    i++;
                    c = s.substring(i, i + 1).charAt(0);
                    break;
                case 0: // 栈中运算符优先级等于当前运算符
                    op.pop(); // 运算符出栈
                    i++;
                    c = s.substring(i, i + 1).charAt(0);
                    break;
                case 1: // 栈中运算符优先级大于当前运算符
                    // 两次取出操作数栈中的数
                    double a = num.pop();
                    double b = num.pop();
                    // 取出运算符栈中的运算符
                    char ss = op.pop();
                    // 计算结果保存在数字栈中
                    num.push(cal(a, ss, b));
                    break;
                }
            }
        }
        return num.peek(); // 表达式计算完毕,返回数字栈中保存的计算结果
    }
    //测试

    public static void main(String[] args) {
        System.out.println(MyCal.calculate("1+2*(3+4)"));
        //System.out.println(MyCal.calculate("1+2*3+5+Math.max(1,3)"));
    }
}


     
     
    
    
   
   
  
  

本文出自:冯立彬的博客



                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值