如何在C#中运行数学表达式字符串
方法1:利用DataTable中的Compute方法
1 string expression = "1+2*3";
2 DataTable eval = new DataTable();object result = eval.Compute(expression, “”);
方法2:利用xPath表达式

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里面的计算表达式方法 该方法的内容被博客园吃掉了。懒得找了
方法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 }

如何在C#中运行数学表达式字符串的更多相关文章
- Oracle中有关数学表达式的语法
Oracle中有关数学表达式的语法 三角函数 SIN ASIN SINHCOS ACOS COSHTA ...
- Nodejs的安装配置及如何在sublimetext2中运行js
Nodejs的安装配置及如何在sublimetext2中运行js听语音 | 浏览:4554 | 更新:2015-06-16 11:29 Nodejs的安装配置及如何在sublimetext2中运行js ...
- 如何在xampp中运行php文件 (WINDOWS)
from:http://blog.sina.com.cn/s/blog_5e87822501011os2.html 入门: 如何在xampp中运行php文件 (WINDOWS) 安装XAMPP启动ap ...
- [转帖]如何在VirtualBox中运行macOS Catalina Beta版本
如何在VirtualBox中运行macOS Catalina Beta版本 secist2019-08-03共2179人围观系统安全 https://www.freebuf.com/articles/ ...
- 理解CSS中的数学表达式calc()
前面的话 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路.本文将介绍calc()的相关内容 定义 数学表达式calc()是calculat ...
- css中的数学表达式calc()
前言 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路. 概念 数学表达式calc()是calculate计算的缩写,它允许使用+.-.*. ...
- Zookeeper客户端cli_st为何在crontab中运行不正常?
实践中,发现直接在命令行终端运行cli_st时,能够得到预期的结果,但一将它放到crontab中,则只收到: bye 相关的一段clit_st源代码如下: if (FD_ISSET(, &rf ...
- 如何在linux中运行sql文件
1.在linux中进入sql命令行 mysql -u root -p 输入密码 2.假设home下面有a.sql文件 先得use databasename,要不会报错 “No Database S ...
- 如何在RichTextBox中改变多个字符串的颜色以及字体
目标:传入目标富文本框以及需要查找的字符串,如果文本框中存在字符串,则改变其颜色和字体 可能因为这个问题比较简单,在网上找了很久,也没有一个好的方法.少有的一些方法,也只是改变第一个找到的字符串的颜色 ...
随机推荐
- 时序分析:串匹配—Brute-Force算法
在使用KMP算法之前,使用了BF算法用于串匹配:原文链接已无法查找..... 设有主串s和子串t,子串t的定位就是要在主串s中找到一个与子串t相等的子串.通常把主串s称为目标串,把子串t ...
- Tomcat Eclipse Debug出现异常
1.可能是java类没有及时更新成class文件2.本地程序没有同步到Tommcat服务器里面3.Servlet类里面加了版本号private static final long serialVers ...
- Qt中采用多线程实现Socket编程
Socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 本文介绍的是Qt中采用多线程Socket编程,由于工作的需要,开始 ...
- Django F查询Q查询Only与Defel
F/Q查询 测试表 from django.db import models # Create your models here. class MyCharField(models.Field): d ...
- vue-路由使用
路由安装 终端下载路由插件 npm install vue-router --save-dev 配置 在main.js中引入插件 //Router 为自定义名 vue-router 为插件的名字 im ...
- python 直接存入Excel表格
def write_excels(self, document): outwb = openpyxl.Workbook() outws = outwb.create_sheet(index=0) fo ...
- eas之设置单元格可编辑
for(int i=0;i<kdtEntrys.getRowCount();i++){ kdtEntrys.getRow(i).getCell("orgUnit").g ...
- [luogu2317 HNOI2005] 星际贸易 (dp)
传送门 Solution 两个dp分开处理, 第一问什么都不考虑直接dp 第二问还有些疑惑,姑且先留坑 Code //By Menteur_Hxy #include <cstdio> #i ...
- Ecshop模板中html_options用法详解
程序部分 <?php $smarty->assign('status_list', $_LANG['cs']); // 订单状态 $smarty->display("ind ...
- 向现有的磁盘组加入/删除ASM磁盘
ASM磁盘组支持动态扩展,我们可以向现有的磁盘组动态加入新的磁盘,新磁盘加入后,Oracle通过后台RBAL进行Rebalance,将当前的数据均衡到新增加的磁盘上.Drop磁盘亦会Rebalance ...