动态表达式计算

  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 }

动态表达式计算

时间: 2024-08-10 13:58:02

动态表达式计算的相关文章

C#动态表达式计算

应该有不少人开发过程中遇到过这样的需求,我们直接看图说话: 如上图所示,其中Entity为实体类,其中包括五个属性,该五个属性的值分别来自于数据库查询结果: 用户通过可视化界面进行某些条件的配置以及某些算法的配置并自动生成表达式或者生成数学模型: 程序中需要通过生成的表达式以及动态从数据库中获取的数据进行算法映射以及自动计算出结果. 该需求这边可以举出几个应用场景: 1.报表设计器 我们可以通过报表设计器设计数据库的映射关系并配置数据之间的算法关系,然后动态生成报表: 2.某些采集工具 定向采集

.NET 表达式计算:Expression Evaluator

Expression Evaluator 是一个轻量级的可以在运行时解析C#表达式的开源免费组件.表达式求值应该在很多地方使用,例如一些工资或者成本核算系统,就需要在后台动态配置计算表达式,从而进行计算求值.相比 NCal,还是这个 Expression Evaluator 比较强大,虽然部分功能有重叠.也都能计算常规的数学表达式. Expression Evaluator 支持的特性有: 支持算术运算符,支持关系运算符,以及逻辑运算符 支持表达式分组和括号,以及递增递减运算符 支持表达式属性访

PHP 实现字符串表达式计算

什么是字符串表达式?即,将我们常见的表达式文本写到了字符串中,如:"$age >= 20",$age 的值是动态的整型变量. 什么是字符串表达式计算?即,我们需要一段程序来执行动态的表达式,如给定一个含表达式的字符串变量并计算其结果,而表达式字符串是动态的,比如为客户A执行的表达式是 $orderCount >= 10,而为客户B执行的表达式是 $orderTotal >= 1000. 场景在哪儿?同一份程序具有完全通用性,但差异就其中一个表达式而已,那么我们需要将其

表达式计算

1 #include<iostream> 2 #include<string> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iomanip> 6 #include<stack> 7 using namespace std; 8 9 #define OK 0 10 #define ERROR -1 11 #define OVERFLOW -1 12 #define OPSETSI

C# - 二叉树表达式计算

很早以前就写过双栈的表达式计算. 这次因为想深入学一下二叉树,网上都是些老掉牙的关于二叉树的基本操作. 感觉如果就学那些概念,没意思也不好记忆.于是动手写了一个表达式计算的应用例子. 这样学习印象才深嘛. 我喜欢逆过来贴代码~ 这是运行结果: cal() 是节点类里的计算方法,从根节点调用,递归所有子节点进行计算.Left,Right分别是左右子节点. 1 public double cal() 2 { 3 if (this.isDig==false) 4 { 5 return CAL(Fuha

Vs2013在Linux开发中的应用(26):表达式计算

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 当VS调试时将鼠标移到一个变量上面的时候,VS将显示这个变量的值,实际上这个时候VS进行了表达式的计算,我们所需要做的,就是把这个过程转换为gdb的命令: Operation Description -enable-pretty-printing enable Python-based pretty-printing -var-create create a variable object -v

HDU 2424-Gary&#39;s Calculator(表达式计算+大数)

Gary's Calculator Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 950    Accepted Submission(s): 209 Problem Description Gary has finally decided to find a calculator to avoid making simple cal

C++实现 逆波兰表达式计算问题

C++实现 逆波兰表达式计算问题 #include <iostream> #include <string> using namespace std; class Stack { private: int size; int top; float *listArray; public: Stack(int sz=20); ~Stack(); bool push(float it);//入栈 bool pop(float& it);//出栈 bool isEmpty();//

爪哇国新游记之二十二----算术表达式计算求值

代码: import java.util.ArrayList; import java.util.List; // 辅助类 class Item{ String value; boolean isNumber; public Item(String value,boolean isNumber){ this.value=value; this.isNumber=isNumber; } public Item(char c,boolean isNumber){ this.value=String.