zoukankan      html  css  js  c++  java
  • 如何在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
  • 相关阅读:
    抽象类和接口的区别
    排序之快速排序(quickSort)
    互联网协议入门(1)
    字符串的操作String
    Java笔试题之SQL语句(单表)
    求职之Java开发所需技能
    【更新完毕啦!】一篇完整的产品体验报告处女作
    阿里2015暑期实习生业务型产品笔试题(附部分参考答案)
    滴滴笔试题(附我的答案)
    【面试】蘑菇街产品运营二面&结果
  • 原文地址:https://www.cnblogs.com/WindBlog/p/2733511.html
Copyright © 2011-2022 走看看