namespace lowZoom { class ExpressionCalculator { const int PLUS_PRIORITY = 1; const int MULTIPLY_PRIORITY = 2; const int POWER_PRIORITY = 3; const int OPEN_PARENTHESES_PRIORITY = 0; const int SIGN_PRIORITY = -1; const String SIGN_CHAR = "#"; /** * 计算中缀表达式 */ public static String Calculate(String expression) { Queue<String> exp = Split(expression); Stack<double> oprd = new Stack<double>(); Stack<String> oprt = new Stack<string>(); oprt.Push(SIGN_CHAR); while (exp.Count != 0) { String op = exp.Dequeue(); try { oprd.Push(Convert.ToDouble(op)); } catch { if (op.Equals("(")) oprt.Push(op); else if (op.Equals(")")) { while (!oprt.Peek().Equals("(")) { double o2 = oprd.Pop(); double o1 = oprd.Pop(); double result = Calculate(o1, o2, oprt.Pop()); oprd.Push(result); } oprt.Pop(); } else if (op.Equals(SIGN_CHAR)) { while (!oprt.Peek().Equals(SIGN_CHAR)) { double o2 = oprd.Pop(); double o1 = oprd.Pop(); double result = Calculate(o1, o2, oprt.Pop()); oprd.Push(result); } } else if (PriorityOf(op) > PriorityOf(oprt.Peek())) oprt.Push(op); else { while (PriorityOf(op) <= PriorityOf(oprt.Peek())) { double o2 = oprd.Pop(); double o1 = oprd.Pop(); double result = Calculate(o1, o2, oprt.Pop()); oprd.Push(result); } oprt.Push(op); } } } return oprd.Pop().ToString(); } static double Calculate(double o1, double o2, String oprt) { double result; switch (oprt) { case "+": result = o1 + o2; break; case "-": result = o1 - o2; break; case "*": result = o1 * o2; break; case "/": result = o1 / o2; break; case "%": result = o1 % o2; break; case "^": result = Math.Pow(o1, o2); break; default: throw new WrongExpresstionException(); } return result; } /** * 整理指定中缀表达式 */ static String Trim(String expression) { // 去除表达式中的空格和等号 expression = expression.Replace(" ", "").Replace("=", ""); // 补完右括号 int openCount = 0; int closeCount = 0; foreach (char ch in expression) switch (ch) { case '(': openCount++; break; case ')': closeCount++; break; } if (openCount > closeCount) expression += new String(')', openCount - closeCount); return expression; } /** * 分离操作符和操作数 */ static Queue<String> Split(String expression) { String[] oprt = { "+", "*", "/", "%", "^", "(", ")" }; //String[] oprtRegex = { @"/+", @"/*", "/", "%", @"/^", @"/(", @"/)" }; expression = Trim(expression); //foreach (String o in oprtRegex) // 右括号后面的减号必为操作符 expression = Regex.Replace(expression, @"(?<=/))-", " - "); // 两个数字之间的减号亦必为操作符 expression = Regex.Replace(expression, @"(?<=/d)-(?=/d)", " - "); // 在负号前加上空格以便分割 expression = expression.Replace("-", " -"); // 其他操作符两边都加上空格以便分割 foreach (String o in oprt) expression = expression.Replace(o, " " + o + " "); //Console.WriteLine(expresion); // 将空白字符作为分割符进行切割 String[] split = Regex.Split(expression, @"/s+"); // 去除空白元素 Queue<String> result = new Queue<string>(); foreach (String str in split) if (str.Length > 0) result.Enqueue(str); result.Enqueue(SIGN_CHAR); return result; } /** * 返回指定操作符的优先级 */ static int PriorityOf(String oprt) { int priority; switch (oprt) { case "+": case "-": priority = PLUS_PRIORITY; break; case "*": case "/": case "%": priority = MULTIPLY_PRIORITY; break; case "(": priority = OPEN_PARENTHESES_PRIORITY; break; case "^": priority = POWER_PRIORITY; break; case SIGN_CHAR: priority = SIGN_PRIORITY; break; default: throw new WrongExpresstionException(); } return priority; } public static void Main() { String expression = "(-5+(2.1--2.9)*6) / (1+24%20)^2 = "; Console.Write(expression); Console.WriteLine(Calculate(expression)); Console.ReadKey(); } } }