• C#实现eval 进行四则运算


         昨天在园子里看到有园友,写了相同标题的一篇文章。重点讲的是中缀表达式转换为后缀表达式的算法,但是实现的四则运算 有bug。其实我没看之前也不懂什么是 中缀和后缀表达式,之前有用过js eval 内置函数,后边一想貌似C#中是没有这样的一个函数,加上自己也没事,就试着自己写了下 这个所谓的四则运算。
        我没有研究计算机是怎么来进行四则运算的,我只是按自己的想法来实现 对 6-2*(5-3)+6/2*(6-3+3)/2 这样一个随意组合的四则运算表达式。
        我的思路是样的:
       <1> 先递归把表达式中的括号中的表达式给算出来,然后将值将之替换

     1         #region 计算括号中的表达式
     2         /// <summary>
     3         /// 获取括号中的计算表达式
     4         /// (递归)
     5         /// </summary>
     6         /// <param name="express"></param>
     7         public void GetBraceExpress(ref string express)
     8         {
     9             int leftBraceMaxIndex = -1;
    10             IList<int> rightBraceMinIndexs = new List<int>();
    11             for (int i = 0; i < express.Length; i++)
    12             {
    13                 if (express[i].ToString() == "(")
    14                 {
    15                     leftBraceMaxIndex = i;
    16                 }
    17                 if (express[i].ToString() == ")")
    18                 {
    19                     rightBraceMinIndexs.Add(i);
    20                 }
    21             }
    22             if (leftBraceMaxIndex != -1 && rightBraceMinIndexs.Count > 0)
    23             {
    24                 int rightBraceIndex = 0;
    25                 foreach (var item in rightBraceMinIndexs)
    26                 {
    27                     if (item > leftBraceMaxIndex)
    28                     {
    29                         rightBraceIndex = item;
    30                         break;
    31                     }
    32                 }
    33 
    34                 string braceExpress = express.Substring(leftBraceMaxIndex, rightBraceIndex - leftBraceMaxIndex + 1);
    35                 double result = CalcExpress(braceExpress.TrimStart('(').TrimEnd(')')); //计算()中的表达式
    36                 express = express.Replace(braceExpress, result.ToString());  //结果替换 ()表达式
    37                 if (express.IndexOf("(") != -1 && express.IndexOf(")") != -1)
    38                 {
    39                     GetBraceExpress(ref express);
    40                     return;
    41                 }
    42             }
    43         }
    44         #endregion
    45 
    46         #region 计算表达式
    47         /// <summary>
    48         /// 计算表达式
    49         /// </summary>
    50         /// <param name="express">表达式</param>
    51         /// <returns>表达式结果</returns>
    52         public double CalcExpress(string express)
    53         {
    54             List<double> numbers = new List<double>(); //表达式中的数字
    55             List<char> operaters = new List<char>();   //表达式中的操作符
    56             int tempIndex = 0;
    57             for (int i = 0; i < express.Length; i++)
    58             {
    59                 if (!char.IsNumber(express[i]) && char.IsNumber(express[i - 1]) && i > 0)
    60                 {
    61                     if (tempIndex != 0)
    62                         tempIndex = tempIndex + 1;
    63                     numbers.Add(double.Parse(express.Substring(tempIndex, i - tempIndex)));
    64                     operaters.Add(express[i]);
    65                     tempIndex = i;
    66                 }
    67             }
    68             numbers.Add(double.Parse(express.Substring(tempIndex + 1, express.Length - tempIndex - 1)));
    69             //开始计算
    70             double result = 0;
    71             if (operaters.Count == 0)
    72             {
    73                 return double.Parse(express);
    74             }
    75             else
    76             {
    77                 CalcMultiplyDivide(numbers, operaters); //计算乘除
    78                 result = CalcAddSubduction(numbers, operaters); //计算加减
    79             }
    80             return result;
    81         }
    82         #endregion
    View Code

     
       <2> 递归将 没有括号的表达式中的乘除计算,将结果替换 乘除表达式

     1         #region 计算乘除
     2         /// <summary>
     3         /// 递归计算表达式中的乘/除运算
     4         /// </summary>
     5         /// <param name="numbers">表达式中的数字集合</param>
     6         /// <param name="operaters">操作符集合</param>
     7         public void CalcMultiplyDivide(List<double> numbers, List<char> operaters)
     8         {
     9             for (int i = 0; i < operaters.Count; i++)
    10             {
    11                 bool temp = false;
    12                 double n = 0;
    13                 if (operaters[i] == '*')
    14                 {
    15                     n = numbers[i] * numbers[i + 1];
    16                     temp = true;
    17                 }
    18                 else if (operaters[i] == '/')
    19                 {
    20                     n = numbers[i] / numbers[i + 1];
    21                     temp = true;
    22                 }
    23                 if (temp)
    24                 {
    25                     operaters.RemoveAt(i);
    26                     numbers.RemoveRange(i, 2);
    27                     numbers.Insert(i, n);
    28                     CalcMultiplyDivide(numbers, operaters);
    29                     break;
    30                 }
    31             }
    32         }
    33         #endregion
    View Code


       <3> 递归算加减,直到表达式中没有操作符,然后返回结果。

     1         #region 计算加减
     2         /// <summary>
     3         /// 递归计算加减
     4         /// </summary> 
     5         /// <param name="numbers">表达式中的数字集合</param>
     6         /// <param name="operaters">操作符集合</param>
     7         /// <returns>计算的结果</returns>
     8         public double CalcAddSubduction(List<double> numbers, List<char> operaters)
     9         {
    10 
    11             for (int i = 0; i < operaters.Count; i++)
    12             {
    13                 bool temp = false;
    14                 double n = 0;
    15                 if (operaters[i] == '+')
    16                 {
    17                     n = numbers[i] + numbers[i + 1];
    18                     temp = true;
    19                 }
    20                 else if (operaters[i] == '-')
    21                 {
    22                     n = numbers[i] - numbers[i + 1];
    23                     temp = true;
    24                 }
    25                 if (temp)
    26                 {
    27                     operaters.RemoveAt(i);
    28                     numbers.RemoveRange(i, 2);
    29                     numbers.Insert(i, n);
    30                     CalcAddSubduction(numbers, operaters);
    31                     break;
    32                 }
    33             }
    34             double result = 0;
    35             if (operaters.Count == 0)
    36                 result = numbers[0];
    37             return result;
    38         }
    39         #endregion
    View Code

    这就可以实现像js eval 方法一样对一个四则运算表达式 计算了。这只是按我自己的思路来实现的,没有考虑性能啊什么的,如大家有什么好的法子,一起讨论下。
    附上demo:http://files.cnblogs.com/joey0210/Calc.rar

      

  • 相关阅读:
    如何修改mysql root密码
    【STL】list基础(转)
    时间控制timer settimeout setinterval
    刷新ArrayCollection的显示控件
    需要科普的网站
    flex 拖拽数据
    常用的资源网站
    as3 性能优化
    对象池
    Bitmap与Bitmapdata
  • 原文地址:https://www.cnblogs.com/joey0210/p/3158648.html
Copyright © 2020-2023  润新知