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:https://files.cnblogs.com/joey0210/Calc.rar

  

 

posted on 2013-06-27 14:30  Joey_zy0210  阅读(3928)  评论(11编辑  收藏  举报

导航