如何在C#中运行数学表达式字符串

简介: 方法1:利用DataTable中的Compute方法 View Code 1 string expression = "1+2*3"; 2 DataTable eval = new DataTable();object result = eval.

方法1:利用DataTable中的Compute方法

View Code
1 string expression = "1+2*3";
2 DataTable eval = new DataTable();object result = eval.Compute(expression, “”);

方法2:利用xPath表达式

View Code
 1 publicstaticdoubleEvaluate(string expression)
 2 {
 3     return(double)newSystem.Xml.XPath.XPathDocument
 4     (newStringReader("<r/>")).CreateNavigator().Evaluate
 5     (string.Format("number({0})",new
 6     System.Text.RegularExpressions.Regex(@"([\+\-\*])")
 7     .Replace(expression," ${1} ")
 8     .Replace("/"," div ")
 9     .Replace("%"," mod ")));
10 }

//方法3:利用python里面的计算表达式方法   该方法的内容被博客园吃掉了。懒得找了

View Code

方法4:在网上找了一个计算表达式的类库

  1  /**/
  2     /// <summary>
  3     /// 动态求值
  4     /// </summary>
  5     public class Evaluator
  6     {
  7         /**/
  8         /// <summary>
  9         /// 计算结果,如果表达式出错则抛出异常
 10         /// </summary>
 11         /// <param name="statement">表达式,如"1+2+3+4"</param>
 12         /// <returns>结果</returns>
 13         public static object Eval(string statement)
 14         {
 15             if (statement.Trim() != string.Empty)
 16             {
 17                 Evaluator evaluator = new Evaluator();
 18                 return evaluator.GetFormulaResult(statement);
 19             }
 20             else
 21             {
 22                 return null;
 23             }
 24         }
 25 
 26 
 27         private object GetFormulaResult(string s)
 28         {
 29             if (s == "")
 30             {
 31                 return null;
 32             }
 33             string S = BuildingRPN(s);
 34 
 35             string tmp = "";
 36             System.Collections.Stack sk = new System.Collections.Stack();
 37 
 38             char c = ' ';
 39             System.Text.StringBuilder Operand = new System.Text.StringBuilder();
 40             double x, y;
 41             for (int i = 0;
 42                 i < S.Length;
 43                 i++)
 44             {
 45                 c = S[i];
 46                 //added c==',' for germany culture
 47                 if (char.IsDigit(c) || c == '.' || c == ',')
 48                 {
 49                     //数据值收集.
 50                     Operand.Append(c);
 51                 }
 52                 else if (c == ' ' && Operand.Length > 0)
 53                 {
 54                     #region 运算数转换
 55                     try
 56                     {
 57                         tmp = Operand.ToString();
 58                         if (tmp.StartsWith("-"))//负数的转换一定要小心...它不被直接支持.
 59                         {
 60                             //现在我的算法里这个分支可能永远不会被执行.
 61                             sk.Push(-((double)Convert.ToDouble(tmp.Substring(1, tmp.Length - 1))));
 62                         }
 63                         else
 64                         {
 65                             sk.Push(Convert.ToDouble(tmp));
 66                         }
 67                     }
 68                     catch
 69                     {
 70                         return null; //
 71                     }
 72                     Operand = new System.Text.StringBuilder();
 73                     #endregion
 74                 }
 75                 else if (c == '+'//运算符处理.双目运算处理.
 76                     || c == '-'
 77                     || c == '*'
 78                     || c == '/'
 79                     || c == '%'
 80                     || c == '^')
 81                 {
 82                     #region 双目运算
 83                     if (sk.Count > 0)/*如果输入的表达式根本没有包含运算符.或是根本就是空串.这里的逻辑就有意义了.*/
 84                     {
 85                         y = (double)sk.Pop();
 86                     }
 87                     else
 88                     {
 89                         sk.Push(0);
 90                         break;
 91                     }
 92                     if (sk.Count > 0)
 93                         x = (double)sk.Pop();
 94                     else
 95                     {
 96                         sk.Push(y);
 97                         break;
 98                     }
 99                     switch (c)
100                     {
101                         case '+':
102                             sk.Push(x + y);
103                             break;
104                         case '-':
105                             sk.Push(x - y);
106                             break;
107                         case '*':
108                             if (y == 0)
109                             {
110                                 sk.Push(x * 1);
111                             }
112                             else
113                             {
114                                 sk.Push(x * y);
115                             }
116                             break;
117                         case '/':
118                             if (y == 0)
119                             {
120                                 sk.Push(x / 1);
121                             }
122                             else
123                             {
124                                 sk.Push(x / y);
125                             }
126                             break;
127                         case '%':
128                             sk.Push(x % y);
129                             break;
130                         case '^'://
131                             if (x > 0)//
132                             {
133                                 //我原本还想,如果被计算的数是负数,又要开真分数次方时如何处理的问题.后来我想还是算了吧.
134                                 sk.Push(System.Math.Pow(x, y));
135                                 //
136                             }
137                             //
138                             else//
139                             {
140                                 //
141                                 double t = y;
142                                 //
143                                 string ts = "";
144                                 //
145                                 t = 1 / (2 * t);
146                                 //
147                                 ts = t.ToString();
148                                 //
149                                 if (ts.ToUpper().LastIndexOf('E') > 0)//
150                                 {
151                                     //
152                                     ;
153                                     //
154                                 }
155                                 //
156                             }
157                             break;
158                     }
159                     #endregion
160                 }
161                 else if (c == '!')//单目取反. )
162                 {
163                     sk.Push(-((double)sk.Pop()));
164                 }
165             }
166             if (sk.Count > 1)
167             {
168                 return null;//;
169             }
170             if (sk.Count == 0)
171             {
172                 return null;//;
173             }
174             return sk.Pop();
175         }
176         /**/
177         /// <summary>
178         /// 
179         /// </summary>
180         private string BuildingRPN(string s)
181         {
182             System.Text.StringBuilder sb = new System.Text.StringBuilder(s);
183             System.Collections.Stack sk = new System.Collections.Stack();
184             System.Text.StringBuilder re = new System.Text.StringBuilder();
185 
186             char c = ' ';
187             //sb.Replace( " ","" );
188             //一开始,我只去掉了空格.后来我不想不支持函数和常量能滤掉的全OUT掉.
189             for (int i = 0;
190                 i < sb.Length;
191                 i++)
192             {
193                 c = sb[i];
194                 //added c==',' for german culture
195                 if (char.IsDigit(c) || c == ',')//数字当然要了.
196                     re.Append(c);
197                 //if( char.IsWhiteSpace( c )||
198                 char.IsLetter(c);//如果是空白,那么不要.现在字母也不要.
199                 //continue;
200                 switch (c)//如果是其它字符...列出的要,没有列出的不要.
201                 {
202                     case '+':
203                     case '-':
204                     case '*':
205                     case '/':
206                     case '%':
207                     case '^':
208                     case '!':
209                     case '(':
210                     case ')':
211                     case '.':
212                         re.Append(c);
213                         break;
214                     default:
215                         continue;
216                 }
217             }
218             sb = new System.Text.StringBuilder(re.ToString());
219             #region 对负号进行预转义处理.负号变单目运算符求反.
220             for (int i = 0; i < sb.Length - 1; i++)
221                 if (sb[i] == '-' && (i == 0 || sb[i - 1] == '('))
222                     sb[i] = '!';
223             //字符转义.
224             #endregion
225             #region 将中缀表达式变为后缀表达式.
226             re = new System.Text.StringBuilder();
227             for (int i = 0;
228                 i < sb.Length;
229                 i++)
230             {
231                 if (char.IsDigit(sb[i]) || sb[i] == '.')//如果是数值.
232                 {
233                     re.Append(sb[i]);
234                     //加入后缀式
235                 }
236                 else if (sb[i] == '+'
237                     || sb[i] == '-'
238                     || sb[i] == '*'
239                     || sb[i] == '/'
240                     || sb[i] == '%'
241                     || sb[i] == '^'
242                     || sb[i] == '!')//.
243                 {
244                     #region 运算符处理
245                     while (sk.Count > 0) //栈不为空时
246                     {
247                         c = (char)sk.Pop();
248                         //将栈中的操作符弹出.
249                         if (c == '(') //如果发现左括号.停.
250                         {
251                             sk.Push(c);
252                             //将弹出的左括号压回.因为还有右括号要和它匹配.
253                             break;
254                             //中断.
255                         }
256                         else
257                         {
258                             if (Power(c) < Power(sb[i]))//如果优先级比上次的高,则压栈.
259                             {
260                                 sk.Push(c);
261                                 break;
262                             }
263                             else
264                             {
265                                 re.Append(' ');
266                                 re.Append(c);
267                             }
268                             //如果不是左括号,那么将操作符加入后缀式中.
269                         }
270                     }
271                     sk.Push(sb[i]);
272                     //把新操作符入栈.
273                     re.Append(' ');
274                     #endregion
275                 }
276                 else if (sb[i] == '(')//基本优先级提升
277                 {
278                     sk.Push('(');
279                     re.Append(' ');
280                 }
281                 else if (sb[i] == ')')//基本优先级下调
282                 {
283                     while (sk.Count > 0) //栈不为空时
284                     {
285                         c = (char)sk.Pop();
286                         //pop Operator
287                         if (c != '(')
288                         {
289                             re.Append(' ');
290                             re.Append(c);
291                             //加入空格主要是为了防止不相干的数据相临产生解析错误.
292                             re.Append(' ');
293                         }
294                         else
295                             break;
296                     }
297                 }
298                 else
299                     re.Append(sb[i]);
300             }
301             while (sk.Count > 0)//这是最后一个弹栈啦.
302             {
303                 re.Append(' ');
304                 re.Append(sk.Pop());
305             }
306             #endregion
307             re.Append(' ');
308             return FormatSpace(re.ToString());
309             //在这里进行一次表达式格式化.这里就是后缀式了.  
310         }
311 
312         /// <summary>  
313         /// 优先级别测试函数.  
314         /// </summary>  
315         /// <param name="opr"></param>  
316         /// <returns></returns>  
317         private static int Power(char opr)
318         {
319             switch (opr)
320             {
321                 case '+':
322                 case '-':
323                     return 1;
324                 case '*':
325                 case '/':
326                     return 2;
327                 case '%':
328                 case '^':
329                 case '!':
330                     return 3;
331                 default:
332                     return 0;
333             }
334         }
335 
336         /// <summary>  
337         /// 规范化逆波兰表达式.
338         /// </summary>  
339         /// <param name="s"></param>  
340         /// <returns></returns>  
341         private static string FormatSpace(string s)
342         {
343             System.Text.StringBuilder ret = new System.Text.StringBuilder();
344             for (int i = 0;
345                 i < s.Length;
346                 i++)
347             {
348                 if (!(s.Length > i + 1 && s[i] == ' ' && s[i + 1] == ' '))
349                     ret.Append(s[i]);
350                 else
351                     ret.Append(s[i]);
352             }
353             return ret.ToString();
354             //.Replace( '!','-' );
355         }
356     }
View Code

 

 

相关文章
|
7月前
|
C#
C#的小例子和字符串(一)
C#的小例子和字符串(一)
148 0
|
7月前
|
C#
C#有关字符串的分割,替换,截取
C#有关字符串的分割,替换,截取
|
2月前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
3月前
|
开发框架 .NET 程序员
C# 去掉字符串最后一个字符的 4 种方法
在实际业务中,我们经常会遇到在循环中拼接字符串的场景,循环结束之后拼接得到的字符串的最后一个字符往往需要去掉,看看 C# 提供了哪4种方法可以高效去掉字符串的最后一个字符
354 0
|
3月前
|
开发框架 自然语言处理 .NET
C#一分钟浅谈:LINQ 查询表达式的使用技巧
【9月更文挑战第6天】LINQ(Language Integrated Query)是C#开发中的强大工具,使查询数据集合变得简单且接近自然语言。本文从基础入手,通过具体示例讲解LINQ查询表达式的使用技巧,包括过滤、排序和分组等操作。同时,文章还探讨了常见问题及解决方法,如性能优化、过早枚举和类型转换等,帮助开发者写出更高效、易维护的代码。
105 15
|
3月前
|
C#
C#一分钟浅谈:Lambda 表达式和匿名方法
本文详细介绍了C#编程中的Lambda表达式与匿名方法,两者均可用于定义无名函数,使代码更简洁易维护。文章通过基础概念讲解和示例对比,展示了各自语法特点,如Lambda表达式的`(parameters) =&gt; expression`形式及匿名方法的`delegate(parameters)`结构。并通过实例演示了两者的应用差异,强调了在使用Lambda时应注意闭包问题及其解决策略,推荐优先使用Lambda表达式以增强代码可读性。
49 8
|
3月前
|
前端开发 C#
C# 一分钟浅谈:字符串操作与正则表达式
本文详细介绍C#中的字符串操作与正则表达式应用,涵盖字符串拼接、分割、查找及替换等基础操作,并通过实例讲解正则表达式的模式匹配、文本替换与分组捕获技巧。同时,文章还探讨了性能优化、复杂度管理和安全性等问题及解决策略,助你提升编程效率,应对实际开发挑战。
82 0
|
5月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
4月前
|
Linux C#
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
|
6月前
|
C#
技术经验分享:c#拆分字符串英文和数字(包括国外所以文字)
技术经验分享:c#拆分字符串英文和数字(包括国外所以文字)
37 0
技术经验分享:c#拆分字符串英文和数字(包括国外所以文字)