公式编辑器

  ERP系统业务繁杂,为应对变化,通常会用到公式编辑器。联想到大学学过的汇编原理,国庆期间一个人没事干,就略微温习了下,花了几个小时写了个公式编辑器。面向对象搞多了,算法能力和记忆力都慢慢弱化了,呜呼哀哉!

  本公式编辑器实现的功能很简单,就是计算加减乘除。未进行公式的校验,也未涉及逻辑运算,目的只是单纯地温习下大学的理论基础,同时希望能给其他人一些启发。采用逆波兰式算法,运行结果如下所示。下载源代码

 

  实现代码如下:

    public class CalculateHelper
    {
        //定义算术运算符的优先级
        private int GetOperatorPriorityLevel(char oper)
        {
            switch (oper)
            {
                case '#':
                    return 0;
                case '+':
                    return 1;
                case '-':
                    return 1;
                case '*':
                    return 2;
                case '/':
                    return 2;
                default:
                    return -1;
            }
        }

        //oper1优先级高于oper2,返回正数,反之返回负数,相等则返回0
        private int ComparePriority(char oper1, char oper2)
        {
            return GetOperatorPriorityLevel(oper1) - GetOperatorPriorityLevel(oper2);
        }

        //中缀表达式转后缀表达式
        public Queue<string> MiddleToSuffix(string expression)
        {
            Stack<char> temporaryStack = new Stack<char>();
            temporaryStack.Push('#');
            Queue<string> suffixExpression = new Queue<string>();
            string temNum = "";
            for (int i = 0; i < expression.Length; i++)
            {
                if (expression[i] == ' ')//过滤空格
                    continue;
                #region 处理数字
                if (char.IsNumber(expression[i]) || expression[i] == '.')
                {
                    temNum += expression[i];
                    if ((i == expression.Length - 1))//字符串已经处理结束
                        suffixExpression.Enqueue(temNum);
                    continue;
                }
                else
                {
                    if (temNum != "")
                        suffixExpression.Enqueue(temNum);
                    temNum = "";
                }
                #endregion
                #region 处理括号
                if (expression[i] == '(')
                    temporaryStack.Push(expression[i]);
                else if (expression[i] == ')')
                {
                    while (temporaryStack.Peek() != '#') //退栈并输出,直至遇到  '('
                    {
                        char top = temporaryStack.Pop();
                        if (top == '(')
                            break;
                        suffixExpression.Enqueue(top.ToString());
                    }
                }
                #endregion
                #region 处理运算符
                else // 是运算符,比较优先级
                {
                    char top = temporaryStack.Peek();
                    while (ComparePriority(expression[i], top) <= 0)//保证栈顶元素优先级最高
                    {
                        suffixExpression.Enqueue(top.ToString());
                        temporaryStack.Pop();
                        top = temporaryStack.Peek();
                    }
                    if (expression[i] != ')') //右括号不入栈
                        temporaryStack.Push(expression[i]);
                }
                #endregion
            }
            while (temporaryStack.Count > 1)
                suffixExpression.Enqueue(temporaryStack.Pop().ToString());
            return suffixExpression;
        }

        private double Calculate(string operand1, string operand2, string oper)
        {
            double oper1 = double.Parse(operand1);
            double oper2 = double.Parse(operand2);
            switch (oper)
            {
                case "+":
                    return oper1 + oper2;
                case "-":
                    return oper1 - oper2;
                case "*":
                    return oper1 * oper2;
                case "/":
                    return oper1 / oper2;
                default:
                    throw new Exception("操作符有误!");
            }
        }

        //计算中缀表达式的结果
        public double GetResult(string expression)
        {
            Queue<string> suffixExpression = MiddleToSuffix(expression);
            Stack<string> resultStack = new Stack<string>();
            while (suffixExpression.Count() > 0)
            {
                string oper = suffixExpression.Dequeue();
                if (oper == "+" || oper == "-" || oper == "*" || oper == "/")//为操作符,就计算
                {
                    string oper2 = resultStack.Pop();
                    string oper1 = resultStack.Pop();
                    string temresult = Calculate(oper1, oper2, oper).ToString();
                    resultStack.Push(temresult);
                }
                else
                    resultStack.Push(oper);
            }
            string result = resultStack.Pop();
            return double.Parse(result);
        }
    }

 

posted @ 2013-10-05 17:04  峰顶飞龙  阅读(996)  评论(0编辑  收藏  举报