zoukankan      html  css  js  c++  java
  • 数学表达式的计算使用正则表达式

            这种方式的基本思想就是循环使用正则表达式找出字符串中不带括号的那一部分,再分析出各个数字和运算符以及函数,并执行运算,然后将结果替换原表达式中相应部分,直到最后不能再进行任何替换。如:

            (3+5)*sin(7+9)   ----->  (3+5)*sin(7+9)  ----->8*sin(7+9)  -----> 8*sin16----> 8*sin16 ------> 8*-0.2879 -----> -2.3

            先定义几个正则表达式:

            static Regex Num = new Regex(@"(\-?\d+\.?\d*)"); //匹配浮点数字
    
            static Regex Power = new Regex(Num.ToString() + @"\^" + Num.ToString());//匹配a^b形式的幂次运算
    
            static Regex AddSub = new Regex(Num.ToString() + "([+-])" + Num.ToString());//匹配加减运算
    
            static Regex MulDiv = new Regex(Num.ToString() + "([*/])" + Num.ToString());//匹配乘除运算
    
            static Regex InnerRegex = new Regex(@"\([^\(\)]+\)");//匹配最底层的括号表达式
    
            static Regex FunctionRegex = new Regex(@"(ln|lg|sin|cos|tan|ctg|sh|ch|th|arcsin|arccos|arctan)" + Num.ToString());//匹配各种数学函数
    
            static Regex LBrackets = new Regex(@"\{|\[");//匹配左括号
    
            static Regex RBrackets = new Regex(@"\}|\]");//匹配右括号
    


    下面就是具体代码了(没有进行任何错误、异常检查):

        public static class Function
        {
            static readonly Regex Num = new Regex(@"(\-?\d+\.?\d*)");
            static readonly Regex Power = new Regex(Num.ToString() + @"\^" + Num.ToString());
            static readonly Regex AddSub = new Regex(Num.ToString() + "([+-])" + Num.ToString());
            static readonly Regex MulDiv = new Regex(Num.ToString() + "([*/])" + Num.ToString());
            static readonly Regex InnerRegex = new Regex(@"\([^\(\)]+\)");
            static readonly Regex FunctionRegex = new Regex(@"(ln|lg|sin|cos|tan|ctg|sh|ch|th|arcsin|arccos|arctan|not)" + Num.ToString());
            static readonly Regex LBrackets = new Regex(@"\{|\[");
            static readonly Regex RBrackets = new Regex(@"\}|\]");
    
            /// <summary>计算表达式</summary>
            /// <param name="Expressions">表达式</param>
            public static string Eval(string Expressions)
            {
                Expressions = Expressions.ToLower();
                Expressions = Expressions.Replace("pi", Math.PI.ToString()).Replace("e", Math.E.ToString());//替换常量
                Expressions = LBrackets.Replace(Expressions, (Match match) => { return "("; });//统一使用小括号
                Expressions = RBrackets.Replace(Expressions, (Match match) => { return ")"; });
                if (Check(Expressions))
                {
                    do
                    {
                        Expressions = InnerRegex.Replace(Expressions, (Match match) =>
                        {
                            return EvalInner(match.Value.Substring(1, match.Value.Length - 2));
                        });
                    }
                    while (InnerRegex.IsMatch(Expressions));
                }
                return EvalInner(Expressions);
            }
    
            /// <summary>用于计算不含括号的表达式的值</summary>
            /// <param name="Expressions">要计算的表达式</param>
            /// <returns>计算结果</returns>
            private static string EvalInner(string Expressions)
            {
                while (FunctionRegex.IsMatch(Expressions))
                {
                    Expressions = FunctionRegex.Replace(Expressions, (Match match) => { return EvalSingle(match.Value); });
                }
    
                while (Power.IsMatch(Expressions))
                {
                    Expressions = Power.Replace(Expressions, (Match match) =>
                    {
                        return System.Math.Pow(double.Parse(match.Groups[0].Value), double.Parse(match.Groups[2].Value)).ToString();
                    });
                }
    
                while (MulDiv.IsMatch(Expressions))
                {
                    Expressions = MulDiv.Replace(Expressions, (Match match) =>
                    {
                        if (match.Value.Contains("*"))
                            return (double.Parse(match.Groups[1].Value) * double.Parse(match.Groups[3].Value)).ToString();
                        else
                            return (double.Parse(match.Groups[1].Value) / double.Parse(match.Groups[3].Value)).ToString();
                    });
                }
    
                while (AddSub.IsMatch(Expressions))
                {
                    Expressions = AddSub.Replace(Expressions, (Match match) =>
                    {
                        if (match.Value.Contains("+"))
                            return (double.Parse(match.Groups[1].Value) + double.Parse(match.Groups[3].Value)).ToString();
                        else
                            return (double.Parse(match.Groups[1].Value) - double.Parse(match.Groups[3].Value)).ToString();
                    });
                }
    
                return Expressions;
            }
    
            /// <summary>用于计算单变量函数表达式的值</summary>
            /// <param name="Expressions">要计算的表达式</param>
            /// <returns>计算结果</returns>
            private static string EvalSingle(string Expressions)
            {
                while (FunctionRegex.IsMatch(Expressions))
                {
                    Expressions = FunctionRegex.Replace(Expressions, (Match match) => { return EvalSingle(match); });
                }
    
                return Expressions;
            }
    
            private static string EvalSingle(Match match)
            {
                //ln|lg|sin|cos|tan|ctg|sh|ch|th|arcsin|arccos|arctan
                double Param = double.Parse(match.Groups[2].Value.Trim('(', ')'));
                double Result = double.NaN;
    
                if (!double.IsNaN(Param))
                {
                    if (match.Value.StartsWith("ln"))
                        Result = System.Math.Log(Param);
                    else if (match.Value.StartsWith("lg"))
                        Result = System.Math.Log10(Param);
                    else if (match.Value.StartsWith("sin"))
                        Result = System.Math.Sin(Param * Math.PI / 180);
                    else if (match.Value.StartsWith("sqrt"))
                        Result = System.Math.Sqrt(Param);
                    else if (match.Value.StartsWith("cos"))
                        Result = System.Math.Cos(Param * Math.PI / 180);
                    else if (match.Value.StartsWith("tan"))
                        Result = System.Math.Tan(Param * Math.PI / 180);
                    else if (match.Value.StartsWith("ctg"))
                        Result = 1 / System.Math.Tan(Param * Math.PI / 180);
                    else if (match.Value.StartsWith("sh"))
                        Result = System.Math.Sinh(Param);
                    else if (match.Value.StartsWith("ch"))
                        Result = System.Math.Cosh(Param);
                    else if (match.Value.StartsWith("th"))
                        Result = System.Math.Tanh(Param);
                    else if (match.Value.StartsWith("arcsin"))
                        Result = System.Math.Asin(Param);
                    else if (match.Value.StartsWith("arccos"))
                        Result = System.Math.Acos(Param);
                    else if (match.Value.StartsWith("arctan"))
                        Result = System.Math.Atan(Param);
                }
    
                return Result.ToString();
            }
    
            /// <summary>对表达式进行检查,确保其格式符合要求</summary>
            /// <param name="Expressions">表达式</param>
            /// <returns>是否符合要求</returns>
            public static bool Check(string Expressions)
            {
                return CheckBrackets(Expressions);
            }
    
            /// <summary>检查括号是否匹配</summary>
            /// <param name="Expressions">表达式</param>
            /// <returns>是否匹配</returns>
            private static bool CheckBrackets(string Expressions)
            {
                int i = 0;
                foreach (char c in Expressions)
                {
                    if (c == '(') { i++; }
                    if (c == ')') { i--; }
                }
                return i == 0;
            }
        }



  • 相关阅读:
    MySql 免安装配置
    MySql 语句优化的几个小建议
    Sharding-JDBC 公共表
    Sharding-JDBC 垂直分库
    Sharding-JDBC 水平分库
    Vuejs基础使用
    webpack配置开发环境和生产环境
    webpack常见应用
    webpack-用loader加载css样式、图片、字体、数据
    webpack核心概念-模式/loader/插件及其他
  • 原文地址:https://www.cnblogs.com/wmesci/p/2736009.html
Copyright © 2011-2022 走看看