首页 > 代码库 > 动态表达式计算

动态表达式计算

  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                         else141                         {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 =http://www.mamicode.com/ Convert.ToDouble(left);154             double rightValue =http://www.mamicode.com/ 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                 else192                 {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                 else226                 {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 = http://www.mamicode.com/m.Groups[1].Value;239             string operatorStr = m.Groups[3].Value;240             string rightValue = http://www.mamicode.com/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*1248         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                 else261                     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