方法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 }