赞
踩
转自:http://www.cnblogs.com/WindBlog/archive/2012/10/22/2733511.html
方法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:在网上找了一个计算表达式的类库
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 }
目前选用方法1,比较快捷,也暂时够用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。