昨天在園子裏看到有園友,寫了相同標題的一篇文章。重點講的是中綴表達式轉換爲後綴表達式的算法,可是實現的四則運算 有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
<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
<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
這就能夠實現像js eval 方法同樣對一個四則運算表達式 計算了。這只是按我本身的思路來實現的,沒有考慮性能啊什麼的,如你們有什麼好的法子,一塊兒討論下。
附上demo:http://files.cnblogs.com/joey0210/Calc.rar函數