C# 如何实现字符串格式数学表达式的数值计算功能?
C# 字符串数学表达式计算实现方案
你可以根据场景选择以下两种实现方案:
方案1:使用成熟第三方库(推荐,快速落地)
可以使用NCalc库,支持绝大多数常用运算符(加减乘除、幂运算、取模、括号、自定义函数、变量等),不需要自己处理复杂的运算符优先级、语法解析逻辑。
使用步骤:
- 通过NuGet安装
NCalc包 - 实现
Calculate方法代码如下:
using NCalc; public static object Calculate(string input) { // NCalc默认^为异或运算符,如需用^表示幂运算,提前替换为**即可 input = input.Replace("^", "**"); Expression expression = new Expression(input); if (expression.HasErrors()) { throw new InvalidOperationException($"表达式解析错误:{expression.Error}"); } return expression.Evaluate(); }
你给出的示例输入"2+2+2+2*5^2/2"调用方法后返回结果为31,符合预期。
方案2:手动实现表达式解析(适合不允许引入第三方依赖的场景)
核心逻辑是先把中缀表达式转换为逆波兰(后缀)表达式,再计算后缀表达式结果,可灵活扩展支持自定义运算符。
示例实现代码:
public static double Calculate(string input) { // 预处理:去掉所有空格 input = input.Replace(" ", ""); var postfix = InfixToPostfix(input); return EvaluatePostfix(postfix); } // 中缀表达式转后缀表达式 private static List<string> InfixToPostfix(string infix) { List<string> postfix = new List<string>(); Stack<char> opStack = new Stack<char>(); Dictionary<char, int> priority = new Dictionary<char, int> { {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}, {'(', 0} }; int i = 0; while (i < infix.Length) { // 处理数字(含小数) if (char.IsDigit(infix[i]) || infix[i] == '.') { string num = ""; while (i < infix.Length && (char.IsDigit(infix[i]) || infix[i] == '.')) { num += infix[i]; i++; } postfix.Add(num); } // 左括号直接入栈 else if (infix[i] == '(') { opStack.Push(infix[i]); i++; } // 右括号弹出运算符直到遇到左括号 else if (infix[i] == ')') { while (opStack.Peek() != '(') { postfix.Add(opStack.Pop().ToString()); } opStack.Pop(); // 丢弃左括号 i++; } // 处理普通运算符 else { while (opStack.Count > 0 && priority[opStack.Peek()] >= priority[infix[i]]) { postfix.Add(opStack.Pop().ToString()); } opStack.Push(infix[i]); i++; } } // 弹出栈内剩余运算符 while (opStack.Count > 0) { postfix.Add(opStack.Pop().ToString()); } return postfix; } // 计算后缀表达式结果 private static double EvaluatePostfix(List<string> postfix) { Stack<double> stack = new Stack<double>(); foreach (var token in postfix) { if (double.TryParse(token, out double num)) { stack.Push(num); } else { double b = stack.Pop(); double a = stack.Pop(); switch (token) { case "+": stack.Push(a + b); break; case "-": stack.Push(a - b); break; case "*": stack.Push(a * b); break; case "/": stack.Push(a / b); break; case "^": stack.Push(Math.Pow(a, b)); break; } } } return stack.Pop(); }
注:上述代码默认支持整数、小数、加减乘除、幂运算、括号运算,可根据需求扩展运算符和自定义函数。
内容的提问来源于stack exchange,提问作者user11933701
相关产品推荐
相关产品推荐

