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> 遞歸將 沒有括號的表達式中的乘除計算,將結果替換 乘除表達式express

 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> 遞歸算加減,直到表達式中沒有操做符,而後返回結果。ide

 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函數

相關文章
相關標籤/搜索