c# 逆波兰算法解析字符串2

此文基于https://www.codeproject.com/Articles/5875/C-Expression-Parser-using-RPN 修改,大部分源码皆来自于此页面

本文增加三角函数计算。

以下贴出调用

1、单次计算

string strExpression = "A*1.0+Sin(A*1.2-B)-COS(C)+3/2-TAN(45)/(1+F)+LOG(G)-1.5*D-abs(0-9)";

Dictionary<string, double> keyValuePairs1 = new Dictionary<string, double>()
{
    {"A",1.23 },{"B",1.23},{"C",1.23},{"F",1.23},{"G",1.23},{"D",1.23},
};
using (Tokenizer Tokenizer = new Tokenizer(strExpression))
{
    IEnumerable<IToken> paramsTokens = Tokenizer.ParamTokens;
    var sst = Tokenizer.EvaluateRPN(keyValuePairs1);
    //System.IO.File.WriteAllLines("D:\\1.txt", ss.Select(y => y.ToString()));
    System.Diagnostics.Debug.WriteLine("sst=" + sst);
}

2、多次计算

string strExpression2 = "A/0.5+B*C";
            Dictionary<string, double[]> keyPairDataList = new Dictionary<string, double[]>();
            int sumCount = 5000;
            keyPairDataList.Add("A", createRandom(1.17906, 0.04953, sumCount));
            keyPairDataList.Add("B", createRandom(1.87478, 0.39739, sumCount));
            keyPairDataList.Add("C", createRandom(2.17914, 0.54957, sumCount));

            List<Dictionary<string, double>> keyValuePairs = new List<Dictionary<string, double>>();
            for (int index = 0; index < sumCount; index++)
            {
                Dictionary<string, double> aa = new Dictionary<string, double>()
                {
                    { "A", keyPairDataList["A"][index]},
                    { "B", keyPairDataList["B"][index]},
                    { "C", keyPairDataList["C"][index]},
                };
                keyValuePairs.Add(aa);
            }
            IEnumerable<object> ss = new List<object>();
            using (Tokenizer Tokenizer = new Tokenizer(strExpression2))
            {
                IEnumerable<IToken> paramsTokens = Tokenizer.ParamTokens;
                ss = Tokenizer.EvaluateRPN(keyValuePairs);
                System.IO.File.WriteAllLines("D:\\1.txt", ss.Select(y => y.ToString()));
            }

类图:

抽象类Token实现:

 /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public abstract class Token : IToken
    {
        protected TokenType tokenType = TokenType.ERR;
        private string szValue = string.Empty;

        /// <summary>
        /// 构造函数
        /// </summary>
        protected Token(string szValue)
        {
            this.szValue = szValue;
        }

        /// <summary>
        /// 返回类型
        /// </summary>
        public TokenType Type
        {
            get { return this.tokenType; }
        }

        /// <summary>
        /// 获取表达式块的值
        /// </summary>
        public string BlockValue
        {
            get { return this.szValue; }
        }

        /// <summary>
        /// 比较符
        /// </summary>
        /// <returns></returns>
        public static bool operator ==(Token left, string right)
        {
            return left.BlockValue == right;
        }

        /// <summary>
        /// 比较符
        /// </summary>
        /// <returns></returns>
        public static bool operator !=(Token left, string right)
        {
            return left.BlockValue != right;
        }

        /// <summary>
        /// 相等
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if ((obj is BracketsToken) == false)
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (ReferenceEquals(obj, null))
                return false;
            return this.szValue == (obj as BracketsToken).szValue;
        }

        /// <summary>
        /// 取得哈希值
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.szValue.GetHashCode();
        }

        /// <summary>
        /// 输出
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0}:{1}", tokenType.ToString(), szValue);
        }

        /// <summary>
        /// 创建Token实例
        /// </summary>
        /// <param name="szValue"></param>
        /// <returns></returns>
        internal static IToken Create(string szValue)
        {
            if (BracketsToken.Map(szValue))
                return new BracketsToken(szValue);
            if (ArithmeticToken.Map(szValue))
                return new ArithmeticToken(szValue);
            if (LogicalToken.Map(szValue))
                return new LogicalToken(szValue);
            if (TriangleToken.Map(szValue))
                return new TriangleToken(szValue);
            if (ConstIntegerToken.Map(szValue))
                return new ConstIntegerToken(szValue);
            if (TimeToken.Map(szValue))
                return new TimeToken(szValue);
            return new ParameterToken(szValue);
        }
    }

所有的实现继承Token,主要分为:

1、操作符类:BracketsToken(括号)、ArithmeticToken(算术运算)、LogicalToken(逻辑运算)、TriangleToken(三角运算)

2、操作数类:ConstIntegerToken(常量计算)、ParameterToken(参数计算)

编写2个接口:

1、IOperator 操作符接口,接口方法包含:IOperand Eval(IOperand left, IOperand right);

2、IOperand 操作数接口,接口属性包含:VarName(参数名)、VarValue(参数值)

解析实现:

 paramTokens.Clear();
            arrFinalExpr.Clear();
            Stack stkOp = new Stack();
            ArrayList bottomList = new ArrayList();
            foreach (Token token in this)
            {
                string szToken = token.BlockValue.Trim();
                if (string.IsNullOrEmpty(szToken))
                    continue;
                if ((token is IOperator) == false)
                {
                    if (token is ParameterToken)
                    {
                        arrFinalExpr.Add(token as ParameterToken);
                        paramTokens.Add(token);
                        continue;
                    }
                    arrFinalExpr.Add((token as IOperand));
                    continue;
                }
                if (token == "(")
                    stkOp.Push(token);
                else if (token == ")")
                {
                    Token popToken;
                    while (((popToken = (Token)stkOp.Pop())) != "(")
                    {
                        arrFinalExpr.Add(popToken);
                        if (stkOp.Count == 0)
                            throw new Exception("Unmatched braces!");
                    }
                }
                else
                {
                    if (stkOp.Count == 0 || (Token)stkOp.Peek() == "(" || IsHigherPrecOperator(token, (Token)stkOp.Peek()))
                        stkOp.Push(token);
                    else
                    {
                        while (stkOp.Count != 0)
                        {
                            if (IsLowerPrecOperator(token, (Token)stkOp.Peek()) || IsEqualPrecOperator(token, (Token)stkOp.Peek()))
                            {
                                Token szTop = (Token)stkOp.Peek();
                                if (szTop == "(")
                                    break;
                                szTop = (Token)stkOp.Pop();
                                arrFinalExpr.Add((szTop as IOperator));
                            }
                            else
                                break;
                        }
                        stkOp.Push(token);
                    }
                }
            }
            while (stkOp.Count != 0)
            {
                Token szTop = (Token)stkOp.Pop();
                if (szTop == "(")
                    throw new Exception("Unmatched braces");
                arrFinalExpr.Add((szTop as IOperator));
            }

计算实现:

 /// <summary>
        /// 执行计算
        /// </summary>
        /// <param name="htValues">参数值</param>
        /// <returns></returns>
        public object EvaluateRPN(Dictionary<string, double> htValues)
        {
            Stack stPad = new Stack();
            foreach (object var in arrFinalExpr)
            {
                object calcVar = var;
                IOperand op1 = null;
                IOperand op2 = null;
                IOperator oprtr = null;
                if (var is ParameterToken && htValues != null)
                    (calcVar as IOperand).VarValue = htValues[(calcVar as IOperand).VarName];
                if (calcVar is IOperand)
                    stPad.Push(calcVar);
                else if (calcVar is IOperator)
                {
                    op2 = (IOperand)stPad.Pop();
                    if ((calcVar is TriangleToken) == false && stPad.Count != 0)
                        op1 = (IOperand)stPad.Pop();
                    oprtr = (IOperator)calcVar;
                    IOperand opRes = oprtr.Eval(op1, op2);
                    stPad.Push(opRes);
                }
            }
            return ((IOperand)stPad.Pop()).VarValue;
        }

下载:https://download.csdn.net/download/fuweiping/15931044 

NET5.0,VS2019

猜你喜欢

转载自blog.csdn.net/fuweiping/article/details/115005767