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

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

 

 

你可能感兴趣的:(字符串)