• 动态表达式计算


      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Text.RegularExpressions;
      6 
      7 namespace CalcTest
      8 {
      9     public class CalculateExpress
     10     {
     11         //验证计算表达式 此正则只适用于C# 其他语言不支持
     12         private static Regex calcExpress = new Regex(@"^s*-?(?>(?<k>(s*-)?(?:d+(?:.d+)?|[a-z]+)(?(k))(?<-k>))(?=s*(?:[-+*/%^)]|$))|(?<!(?:^|()s*)[+*/%^](?=s*[(a-zA-Z0-9])|-(?=s*[(a-zA-Z0-9])|s+|(?:[A-Z]+)?((?!s*))(?<Open>)|)(?=s*(?:[-+*/%^)]|$))(?<-Open>))*(?(Open)(?!))$",RegexOptions.IgnoreCase);
     13         private static Regex inBracket = new Regex(@"(([0-9+-*/.^]+))");//匹配括号表达式
     14         private static Regex twoNumberPow = new Regex(@"(?(-?d+(.d+)?))?([^])(?(-?d+(.d+)?))?");//幂运算表达式
     15         private static Regex twoNumberMD = new Regex(@"(?(-?d+(.d+)?))?([*/])(?(-?d+(.d+)?))?");//乘除运算表达式
     16         private static Regex twoNumberAE = new Regex(@"(?(-?d+(.d+)?))?([+-])(?(-?d+(.d+)?))?");//加减运算表达式
     17         private static Regex snRegex = new Regex(@"(-?d+(.d+)?[Ee]d+)");//科学计数法
     18         //自定义函数列表
     19         private IList<FunctionReflect> functions = new List<FunctionReflect>();
     20 
     21         public IList<string> listInfo = new List<string>();
     22 
     23         public IList<FunctionReflect> Functions
     24         {
     25             get { return functions; }
     26             set { functions = value; }
     27         }
     28 
     29         //函数委托
     30         public delegate string RunFunction(string[] args);
     31 
     32         //sin 正弦函数
     33         private string runFunctionSin(string[] args)
     34         {
     35             return Math.Sin(Convert.ToDouble(args[0])).ToString();
     36         }
     37 
     38         //cos 余弦函数
     39         private string runFunctionCos(string[] args)
     40         {
     41             return Math.Cos(Convert.ToDouble(args[0])).ToString();
     42         }
     43 
     44         //tan 正切函数
     45         private string runFunctionTan(string[] args)
     46         {
     47             return Math.Tan(Convert.ToDouble(args[0])).ToString();
     48         }
     49 
     50         //sqrt 开方函数
     51         private string runFunctionSqrt(string[] args)
     52         {
     53             return Math.Sqrt(Convert.ToDouble(args[0])).ToString();
     54         }
     55 
     56         //自定义函数类
     57         public class FunctionReflect
     58         {
     59             public FunctionReflect(Regex regx, RunFunction runFun)
     60             {
     61                 this.FunRegex = regx;
     62                 this.FunDelegate = runFun;
     63             }
     64 
     65             public FunctionReflect(string funname, RunFunction runFun)
     66             {
     67                 this.FunRegex = buildFunctionRegx(funname);
     68                 this.FunDelegate = runFun;
     69             }
     70 
     71             //自定义函数正则 用于计算时匹配表达式
     72             public Regex FunRegex { get; set; }
     73 
     74             //函数执行委托
     75             public RunFunction FunDelegate { get; set; }
     76 
     77             //根据函数名创建正则表达式 格式为 函数名(数字)
     78             private Regex buildFunctionRegx(string funName)
     79             {
     80                 string regex = funName + @"(([0-9+-*/.^()]+?))";
     81                 return new Regex(regex);
     82             }
     83         }
     84 
     85         //注册函数
     86         private void functionRegxRegister()
     87         {
     88             FunctionReflect funRef = null;
     89 
     90             funRef = new FunctionReflect("sin", runFunctionSin); functions.Add(funRef);
     91             funRef = new FunctionReflect("cos", runFunctionCos); functions.Add(funRef);
     92             funRef = new FunctionReflect("tan", runFunctionTan); functions.Add(funRef);
     93             funRef = new FunctionReflect("sqrt", runFunctionSqrt); functions.Add(funRef);
     94 
     95         }
     96 
     97         //判断是否存在自定义函数
     98         private bool hasFunction(string exp)
     99         {
    100             bool result = false;
    101             foreach (FunctionReflect fr in functions)
    102             {
    103                 if (fr.FunRegex.Match(exp).Success)
    104                 {
    105                     result = true;
    106                     break;
    107                 }
    108             }
    109             return result;
    110         }
    111 
    112         //计算自定义函数
    113         private string calcFunction(string exp)
    114         {
    115             Match m = null;
    116             StringBuilder sbExpress = new StringBuilder(exp);
    117             while (true)
    118             {
    119                 if (!hasFunction(sbExpress.ToString()))
    120                     break;
    121 
    122                 foreach (FunctionReflect fr in functions)
    123                 {
    124                     while (true)
    125                     {
    126                         m = fr.FunRegex.Match(sbExpress.ToString());
    127                         if (m.Success)
    128                         {
    129                             string repExp = m.Groups[0].Value;
    130                             string[] calcExp = m.Groups[1].Value.Split(',');
    131                             IList<string> args = new List<string>();
    132                             foreach (string param in calcExp)
    133                             {
    134                                 args.Add(CalcSimpleExpress(param));
    135                             }
    136                             string result = fr.FunDelegate(args.ToArray());
    137                             sbExpress = sbExpress.Replace(repExp, result, m.Index, m.Length);
    138                             listInfo.Add(repExp + " 计算后 " + sbExpress.ToString());
    139                         }
    140                         else
    141                         {
    142                             break;
    143                         }
    144                     }
    145                 }
    146             }
    147             return sbExpress.ToString();
    148         }
    149 
    150         //计算两个数(+-*/^)的结果
    151         private string calcTwoNumber(string left, string oper, string right)
    152         {
    153             double leftValue = Convert.ToDouble(left);
    154             double rightValue = Convert.ToDouble(right);
    155             switch (oper)
    156             {
    157                 case "+": return (leftValue + rightValue).ToString();
    158                 case "-": return (leftValue - rightValue).ToString();
    159                 case "*": return (leftValue * rightValue).ToString();
    160                 case "/": return (leftValue / rightValue).ToString();
    161                 case "^": return Math.Pow(leftValue, rightValue).ToString();
    162                 default: return string.Empty;
    163             }
    164         }
    165 
    166         //将科学计数法表达式转化为数字
    167         private string snToNormal(string sn)
    168         {
    169             sn = sn.ToLower().Trim();
    170             string[] temp = sn.Split('e');
    171             double l = Convert.ToDouble(temp[0]);
    172             double r = Convert.ToDouble(temp[1]);
    173             string result = (Math.Pow(10, r) * l).ToString();
    174             return result;
    175         }
    176 
    177         //替换表达式中的科学计数法表达式转化为数字
    178         public string snReplace(string exp)
    179         {
    180             string express = exp.Trim();
    181             StringBuilder sbExpress = new StringBuilder(express);
    182             while (true)
    183             {
    184                 Match m = snRegex.Match(sbExpress.ToString());
    185                 if (m.Success)
    186                 {
    187                     string sn = m.Groups[0].Value;
    188                     sbExpress = sbExpress.Replace(sn, snToNormal(sn), m.Index, m.Length);
    189                     listInfo.Add(sn + " 计算后 " + sbExpress.ToString());
    190                 }
    191                 else
    192                 {
    193                     break;
    194                 }
    195 
    196             }
    197 
    198 
    199             return sbExpress.ToString();
    200         }
    201 
    202         //计算不带括号的表达式
    203         private string calcExpressNoBracket(String exp)
    204         {
    205             Match m = null;
    206             string express = exp;
    207 
    208             operationReplace(ref m, ref express, twoNumberPow);
    209             operationReplace(ref m, ref express, twoNumberMD);
    210             operationReplace(ref m, ref express, twoNumberAE);
    211 
    212             return express;
    213         }
    214 
    215         //将表达式中的相邻的两个数计算出来(循环所有)
    216         private void operationReplace(ref Match m, ref string express, Regex reg)
    217         {
    218             while (true)
    219             {
    220                 m = reg.Match(express);
    221                 if (m.Success)
    222                 {
    223                     express = calcReplace(m, express);
    224                 }
    225                 else
    226                 {
    227                     break;
    228                 }
    229 
    230             }
    231         }
    232 
    233         //将表达式中的相邻的两个数计算出来(仅供operationReplace调用)
    234         private string calcReplace(Match m, string express)
    235         {
    236             StringBuilder sbExpress = new StringBuilder(express);
    237             string twoNumberExp = m.Groups[0].Value;
    238             string leftValue = m.Groups[1].Value;
    239             string operatorStr = m.Groups[3].Value;
    240             string rightValue = m.Groups[4].Value;
    241             string result = calcTwoNumber(leftValue, operatorStr, rightValue);
    242             sbExpress = sbExpress.Replace(twoNumberExp, result, m.Index, m.Length);
    243             listInfo.Add(twoNumberExp + " 计算后 " + sbExpress.ToString());
    244             return sbExpress.ToString();
    245         }
    246 
    247         // 计算括号内的表达式 如 1*(3-2) 的话就会把 3-2 计算出来 得到 1*1
    248         private string clearBracket(string exp)
    249         {
    250             Match m = null;
    251             StringBuilder sbExpress = new StringBuilder(exp);
    252             while (true)
    253             {
    254                 m = inBracket.Match(sbExpress.ToString());
    255                 if (m.Success)
    256                 {
    257                     sbExpress = sbExpress.Replace(m.Groups[0].Value, calcExpressNoBracket(m.Groups[1].Value), m.Index, m.Length);
    258                     listInfo.Add(m.Groups[0].Value + " 计算后 " + sbExpress.ToString());
    259                 }
    260                 else
    261                     break;
    262             }
    263             return sbExpress.ToString();
    264         }
    265 
    266         //计算不带自定义函数的数学表达式(不能带科学计数法)
    267         public string CalcSimpleExpress(string exp)
    268         {
    269             string express = exp.Trim();
    270 
    271             //先计算括号内的
    272             express = clearBracket(express);
    273 
    274             //再计算括号外的
    275             return calcExpressNoBracket(express);
    276         }
    277 
    278         //计算不带自定义函数的数学表达式(不能带科学计数法)
    279         public string CalcNoFunExpress(string exp)
    280         {
    281             string express = exp.Trim();
    282 
    283             //先计算括号内的
    284             express = clearBracket(express);
    285 
    286             //再计算括号外的
    287             return calcExpressNoBracket(express);
    288         }
    289 
    290         //计算带自定义函数的数学表达式
    291         public string CalcFunExpress(string exp)
    292         {
    293             //注册自定义函数
    294             functionRegxRegister();
    295 
    296             string express = exp.Trim();
    297 
    298             //转换科学计数法
    299             express = snReplace(express);
    300 
    301             //计算自定义函数
    302             express = calcFunction(express);
    303 
    304             //计算最终结果
    305             return CalcSimpleExpress(express);
    306         }
    307 
    308         //验证数学表达式是否合法
    309         public static bool RegexCalcExpress(string exp)
    310         {
    311             return calcExpress.IsMatch(exp.Trim());
    312         }
    313     }
    314 }
    View Code
  • 相关阅读:
    NS3 使用NS3工具PyViz
    ns-3 NetAnim遇到了一个问题
    NS-3 MyFirstScriptExample
    Ubuntu下Eclipse安装与编译ns-3遇见的各种问题
    Ubuntu 12.04 安装JDK
    近期学习的参考博客链接
    Win7上安装WMware虚拟机和Ubuntu操作系统
    C++课程小结 继承与派生
    C语言中生产随机数 rand()函数
    PTA第三次上机
  • 原文地址:https://www.cnblogs.com/fishes/p/3795800.html
Copyright © 2020-2023  润新知