数学表达式的计算-使用正则表达式

13 篇文章 0 订阅
10 篇文章 1 订阅

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

        (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;
        }
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值