从后缀表示法构建表达式树的问题

时间:2012-07-04 11:20:05

标签: algorithm language-agnostic expression-trees postfix-notation

我正在为简单的数学表达式写出一个推动者(常数和简单 算术)。

我遇到的问题是从后缀格式的表达式构建表达式树。我在大多数情况下都做得很好,but not with this example from Wikipedia

如果我评估表达式3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3,即使结果应为3,0001220703125,我也会得到结果3,001953125。 原因似乎是表达式树看起来像3+((4*2)/((1-5)^(2^3)))而不是(3+((4*2)/(((1-5)^2)^3)))

原始表达式的后缀表示法看起来像3 4 2 * 1 5 − 2 3 ^ ^ / +

有关如何获取表达式树的任何建议吗?
下面是表达式树代码的后缀和一些在C#中的测试,但应该是非常明显的。

public MathExpression Parse()
{
    var tokens = this.ToPostFix(_tokens);
    var stack = new Stack<MathExpression>();
    foreach(token in tokens)
    {
        if(token.IsOperand())
        {
            // Push the operand on the stack.
            stack.Push(new ConstantExpression(token.Value));
        }
        else
        {
            Debug.Assert(token.Type == TokenType.Operator, "Expected operator.");
            var op = (Operator)token.Value;
            var right = stack.Pop();
            var left = stack.Pop();
            var expression = new ArithmeticExpression(op, left, right);
            stack.Push(expression);
        }
    }
    Debug.Assert(stack.Count == 1, "More than one expression on stack.");
    return stack.Pop();
}

还有一些测试:

[Test]
public void Wikipedia_Example_Can_Be_Evaluated()
{
    var expected = 3+4*2/(1-5)^2^3; // 3,001953125
    var actual = MathExpression.Parse("3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3")
                               .Evaluate(); // 3,0001220703125
    Assert.AreEqual(expected, actual); // Not equal :(
}

[Test]
public void Can_Convert_To_Prefix()
{
    string expected = "3 4 2 * 1 5 − 2 3 ^ ^ / +"
    string actual = MathExpression.ToPostFix("3+4*2/(1-5)^2^3")
    Assert.AreEqual(expected, actual); // Works as expected
}

1 个答案:

答案 0 :(得分:5)

WikiPedia页面包含此评论:

  

^从右到左进行评估

我没有看到您的代码考虑到这一点,^被视为与其他运算符相同,因为左关联。

这意味着您的解释可能是错误的:

x ^ 2 ^ 3 =&gt; x^(2^3) =&gt; x 2 3 ^ ^

您的代码和原始答案(3,0001220703125)是正确的。