将字符串转换为允许更改运算符前缀的公式



假设我有一个公式字符串(例如string formula = "(2 + 3 * 3) + 7"(,但我希望多值运算符不具有比其他运算符更高的顺序优先级。因此,在上面的例子中,除了仍然具有优先级的括号外,它们将简单地从左到右求解。

我一直在网上找,但找不到解决这个问题的办法。我发现了非常古老的StackOverflow线程,但评论中的人提到这些方法已经过时了,我不确定它们是否允许更改运算符的优先级,它们只会按面值处理字符串。

我也找到了Flee,但没有关于如何使用它的教程,我也没有找到我需要添加到引用中的dll,以将框架实现到我的项目中。

我在这里留白。你们能帮忙吗?

谢谢!

将字符串转换为公式的类是:

public class StringToFormula
{
private string[] _operators = { "-", "+", "/", "*", "^" };
private Func<double, double, double>[] _operations = {
(a1, a2) => a1 - a2,
(a1, a2) => a1 + a2,
(a1, a2) => a1 / a2,
(a1, a2) => a1 * a2,
(a1, a2) => Math.Pow(a1, a2)
};
public double Eval(string expression)
{
List<string> tokens = getTokens(expression);
Stack<double> operandStack = new Stack<double>();
Stack<string> operatorStack = new Stack<string>();
int tokenIndex = 0;
while (tokenIndex < tokens.Count)
{
string token = tokens[tokenIndex];
if (token == "(")
{
string subExpr = getSubExpression(tokens, ref tokenIndex);
operandStack.Push(Eval(subExpr));
continue;
}
if (token == ")")
{
throw new ArgumentException("Mis-matched parentheses in expression");
}
//If this is an operator  
if (Array.IndexOf(_operators, token) >= 0)
{
while (operatorStack.Count > 0 && Array.IndexOf(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek()))
{
string op = operatorStack.Pop();
double arg2 = operandStack.Pop();
double arg1 = operandStack.Pop();
operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
}
operatorStack.Push(token);
}
else
{
operandStack.Push(double.Parse(token));
}
tokenIndex += 1;
}
while (operatorStack.Count > 0)
{
string op = operatorStack.Pop();
double arg2 = operandStack.Pop();
double arg1 = operandStack.Pop();
operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
}
return operandStack.Pop();
}
private string getSubExpression(List<string> tokens, ref int index)
{
StringBuilder subExpr = new StringBuilder();
int parenlevels = 1;
index += 1;
while (index < tokens.Count && parenlevels > 0)
{
string token = tokens[index];
if (tokens[index] == "(")
{
parenlevels += 1;
}
if (tokens[index] == ")")
{
parenlevels -= 1;
}
if (parenlevels > 0)
{
subExpr.Append(token);
}
index += 1;
}
if ((parenlevels > 0))
{
throw new ArgumentException("Mis-matched parentheses in expression");
}
return subExpr.ToString();
}
private List<string> getTokens(string expression)
{
string operators = "()^*/+-";
List<string> tokens = new List<string>();
StringBuilder sb = new StringBuilder();
foreach (char c in expression.Replace(" ", string.Empty))
{
if (operators.IndexOf(c) >= 0)
{
if ((sb.Length > 0))
{
tokens.Add(sb.ToString());
sb.Length = 0;
}
tokens.Add(c.ToString());
}
else
{
sb.Append(c);
}
}
if ((sb.Length > 0))
{
tokens.Add(sb.ToString());
}
return tokens;
}
}

最初的版本是Here,我修复了一个小错误,使其功能齐全。

调用示例:

string formula = "(2 + 3 * 3) + 7";
StringToFormula stf = new StringToFormula();
double result = stf.Eval(formula);

结果是

18

最新更新