示例#1
0
 public void ProcParentheses(int index, OperatorType op)
 {
     if (op == OperatorType.L_Parentheses)             //左括号
     {
         needOp          = false;
         needParentheses = false;
         stackOp.Push(op);
     }
     else if (op == OperatorType.R_Parentheses)             //右括号
     {
         bool find = false;
         //如果是函数,则此处为函数的参数个数
         //通过统计逗号的个数得出参数的个数
         int funcParam = 1;
         while (stackOp.Count > 0)
         {
             if (stackOp.Peek() != OperatorType.L_Parentheses)
             {
                 OperatorType opPop = stackOp.Pop();
                 if (opPop == OperatorType.Comma)
                 {
                     funcParam++;
                 }
                 else
                 {
                     rePoland.Add(new ExpressionToken(TokenType.Operator, opPop));
                 }
             }
             else
             {
                 stackOp.Pop();
                 find = true;
                 break;
             }
         }
         if (!find)
         {
             throw new ExpressionException("括号不匹配.(缺少左括号)", 1003);
         }
         //如果再前一个是函数,也要加到 rePoland 中
         if (stackOp.Count > 0)
         {
             OperatorType opPrev = stackOp.Peek();
             if (IsFunc(opPrev))
             {
                 //先判断函数的参数个数是否正确
                 FunctionBase func = FuncFactory.GetFunc((int)opPrev);
                 if (func.ParamCount != funcParam)
                 {
                     throw new ExpressionException("函数(" + func.Name + ")参数个数不正确\n"
                                                   + "应为" + func.ParamCount + "个,"
                                                   + "实为" + funcParam + "个");
                 }
                 rePoland.Add(new ExpressionToken(TokenType.Operator, stackOp.Pop()));
             }
         }
     }
 }
示例#2
0
        /// <summary>
        /// 计算二元表达式的值
        /// </summary>
        public object CalcOperator(OperatorType op, decimal?[] data)
        {
            if (IsBaseOperator(op))
            {
                decimal?d1 = data[0];
                decimal?d2 = data[1];
                if (d1 == null || d2 == null)
                {
                    return(DBNull.Value);
                }
                switch (op)
                {
                case OperatorType.Plus:
                    return(d1 + d2);

                case OperatorType.Subtract:
                    return(d1 - d2);

                case OperatorType.MultiPly:
                    return(d1 * d2);

                case OperatorType.Divide:
                    if (d2 == 0)
                    {
                        throw new DivideByZeroException();
                    }
                    return(d1 / d2);

                case OperatorType.Power:                        //幂运算
                    return(Math.Pow((double)d1, (double)d2));
                }
            }
            else if (IsFunc(op))
            {
                FunctionBase func = FuncFactory.GetFunc((int)op);
                if (func == null)
                {
                    throw new ExpressionException("不可识别的函数名.");
                }
                else
                {
                    func.Data = data;
                    try
                    {
                        return(func.Calc());
                    }
                    catch (Exception ex)
                    {
                        throw new ExpressionException("函数计算出错:" + ex.Message, 9000);
                    }
                }
            }
            return(0);
        }
示例#3
0
        private object CalcInner()
        {
            int index = 0;
            //存放常数表
            List <decimal?> digit = new List <decimal?>();
            //备份表达式
            List <ExpressionToken> polandCalc = new List <ExpressionToken>(rePoland.Count);

            for (int i = 0; i < rePoland.Count; i++)
            {
                polandCalc.Add(rePoland[i]);
            }
            while (index < polandCalc.Count)
            {
                if (polandCalc.Count == 1 && polandCalc[0].Type == TokenType.Numeric)
                {
                    break;
                }
                ExpressionToken token = polandCalc[index];
                switch (token.Type)
                {
                case TokenType.Numeric:
                    if (polandCalc[index].Data == DBNull.Value)
                    {
                        digit.Add(null);
                    }
                    else
                    {
                        digit.Add(Convert.ToDecimal(polandCalc[index].Data));
                    }
                    index++;
                    break;

                //case TokenType.Variant:
                //    //将变量替换为常量
                //    polandCalc[index].Data = GetVariantValue(token);
                //    polandCalc[index].Type = TokenType.Numeric;
                //    break;
                case TokenType.Operator:
                    int paramCount = 2;                             //一般是二元式,需要二个参数
                    //函数
                    if (IsFunc((OperatorType)token.Data))
                    {
                        FunctionBase func = FuncFactory.GetFunc((int)(OperatorType)token.Data);
                        if (func == null)
                        {
                            throw new ExpressionException("不可识别的函数名.");
                        }
                        paramCount = func.ParamCount;
                    }
                    //计算前面两个数的值
                    if (digit.Count < paramCount)
                    {
                        throw new ExpressionException("缺少操作数", 1002);
                    }
                    //传入参数
                    decimal?[] data = new decimal?[paramCount];
                    for (int i = 0; i < paramCount; i++)
                    {
                        data[i] = digit[index - paramCount + i];
                    }
                    polandCalc[index - paramCount].Data = CalcOperator((OperatorType)token.Data, data);
                    //将参数从 repoland 中移除
                    for (int i = 0; i < paramCount; i++)
                    {
                        polandCalc.RemoveAt(index - i);
                        digit.RemoveAt(index - i - 1);
                    }
                    index -= paramCount;
                    break;

                default:
                    break;
                }
            }
            if (polandCalc.Count == 1)
            {
                switch (polandCalc[0].Type)
                {
                case TokenType.Numeric:
                    return(polandCalc[0].Data);

                default:
                    throw new ExpressionException("缺少操作数", 1002);
                }
            }
            else
            {
                throw new ExpressionException("缺少操作符或操作数", 1002);
            }
        }