如何在C#中解析数学表达式?

可能重复:
.NET中是否有字符串数学计算器?

C#可以将数学表达式(如y = 3 * x + 3)解析为字符串吗? 如果是的话,好吗? 我感谢您的帮助。

这是我前一段时间编写的一些代码,用于解析中缀(运算符操作数运算符)方程。 有一些小类和辅助函数缺失,但实现它们应该相当容易。 如果您需要它们或任何帮助,请告诉我,我可以将它们上传到某个地方。

这是Dijkstra的Shunting-yard算法的基本实现

public Operand ExpressionTree { get; private set; } private Stack stack = new Stack(); private Queue outputQueue = new Queue(); private void ParseFormulaString() { //Dijkstra's Shunting Yard Algorithm Regex re = new Regex(@"([\+\-\*\(\)\^\/\ ])"); List tokenList = re.Split(formulaString).Select(t => t.Trim()).Where(t => t != "").ToList(); for (int tokenNumber = 0; tokenNumber < tokenList.Count(); ++tokenNumber) { String token = tokenList[tokenNumber]; TokenClass tokenClass = GetTokenClass(token); switch (tokenClass) { case TokenClass.Value: outputQueue.Enqueue(new Value(token)); break; case TokenClass.Function: stack.Push(new Function(token, 1)); break; case TokenClass.Operator: if (token == "-" && (stack.Count == 0 || tokenList[tokenNumber - 1] == "(")) { //Push unary operator 'Negative' to stack stack.Push(new Negative()); break; } if (stack.Count > 0) { String stackTopToken = stack.Peek().Token; if (GetTokenClass(stackTopToken) == TokenClass.Operator) { Associativity tokenAssociativity = GetOperatorAssociativity(token); int tokenPrecedence = GetOperatorPrecedence(token); int stackTopPrecedence = GetOperatorPrecedence(stackTopToken); if (tokenAssociativity == Associativity.Left && tokenPrecedence <= stackTopPrecedence || tokenAssociativity == Associativity.Right && tokenPrecedence < stackTopPrecedence) { outputQueue.Enqueue(stack.Pop()); } } } stack.Push(new BinaryOperator(token, Operator.OperatorNotation.Infix)); break; case TokenClass.LeftParen: stack.Push(new LeftParenthesis()); break; case TokenClass.RightParen: while (!(stack.Peek() is LeftParenthesis)) { outputQueue.Enqueue(stack.Pop()); } stack.Pop(); if (stack.Count > 0 && stack.Peek() is Function) { outputQueue.Enqueue(stack.Pop()); } break; } if (tokenClass == TokenClass.Value || tokenClass == TokenClass.RightParen) { if (tokenNumber < tokenList.Count() - 1) { String nextToken = tokenList[tokenNumber + 1]; TokenClass nextTokenClass = GetTokenClass(nextToken); if (nextTokenClass != TokenClass.Operator && nextTokenClass != TokenClass.RightParen) { tokenList.Insert(tokenNumber + 1, "*"); } } } } while (stack.Count > 0) { Operand operand = stack.Pop(); if (operand is LeftParenthesis || operand is RightParenthesis) { throw new ArgumentException("Mismatched parentheses"); } outputQueue.Enqueue(operand); } String foo = String.Join(",", outputQueue.Select(t => t.Token).ToArray()); String bar = String.Join("", tokenList.ToArray()); Stack expressionStack = new Stack(); while (outputQueue.Count > 0) { Operand operand = outputQueue.Dequeue(); if (operand is Value) { expressionStack.Push(operand); } else { if (operand is BinaryOperator) { BinaryOperator op = (BinaryOperator)operand; Operand rightOperand = expressionStack.Pop(); Operand leftOperand = expressionStack.Pop(); op.LeftOperand = leftOperand; op.RightOperand = rightOperand; } else if (operand is UnaryOperator) { ((UnaryOperator)operand).Operand = expressionStack.Pop(); } else if (operand is Function) { Function function = (Function)operand; for (int argNum = 0; argNum < function.NumArguments; ++argNum) { function.Arguments.Add(expressionStack.Pop()); } } expressionStack.Push(operand); } } if (expressionStack.Count != 1) { throw new ArgumentException("Invalid formula"); } ExpressionTree = expressionStack.Pop(); } private TokenClass GetTokenClass(String token) { double tempValue; if (double.TryParse(token, out tempValue) || token.Equals("R", StringComparison.CurrentCultureIgnoreCase) || token.Equals("S", StringComparison.CurrentCultureIgnoreCase)) { return TokenClass.Value; } else if (token.Equals("sqrt", StringComparison.CurrentCultureIgnoreCase)) { return TokenClass.Function; } else if (token == "(") { return TokenClass.LeftParen; } else if (token == ")") { return TokenClass.RightParen; } else if (binaryInfixOperators.Contains(token)) { return TokenClass.Operator; } else { throw new ArgumentException("Invalid token"); } } private Associativity GetOperatorAssociativity(String token) { if (token == "^") return Associativity.Right; else return Associativity.Left; } private int GetOperatorPrecedence(String token) { if (token == "+" || token == "-") { return 1; } else if (token == "*" || token == "/") { return 2; } else if (token == "^") { return 3; } else { throw new ArgumentException("Invalid token"); } } 

可能是以下副本:

.NET中是否有字符串数学计算器?

简短的回答是否定的,长期的答案请看链接。 (我推荐’coppercoders’解决方案。)

你为什么不使用Simple Math Parser或者同样的东西? 链接文字

我在最近的Silverlight应用程序中通过使用正则表达式(为安全起见)擦除字符串并将其传递给JavaScript评估程序来获得廉价的方法。 它实际上工作得很好,但我承认这是一个黑客攻击。

http://josheinstein.com/blog/index.php/2010/03/mathevalconverter