Algorithm 从后缀符号构建表达式树时出现的问题

Algorithm 从后缀符号构建表达式树时出现的问题,algorithm,language-agnostic,expression-trees,postfix-notation,Algorithm,Language Agnostic,Expression Trees,Postfix Notation,我目前正在为简单的数学表达式(常数和简单的 算术) 我遇到的问题是从后缀格式的表达式构建表达式树。我所做的在大多数情况下都很好 如果我计算表达式3+4*2/(1-5)^2^3,我会得到结果3001220703125,即使结果应该是3001953125。 这似乎是因为表达式树看起来像3+((4*2)/(1-5)^(2^3)),而不是(3+((4*2)/((1-5)^2)^3)) 原始表达式的后缀表示法类似于3 4 2*1 5− 2 3^/+ 有什么建议可以让表达式树成为我想要的样子吗? 下面是表达

我目前正在为简单的数学表达式(常数和简单的 算术)

我遇到的问题是从后缀格式的表达式构建表达式树。我所做的在大多数情况下都很好

如果我计算表达式
3+4*2/(1-5)^2^3
,我会得到结果
3001220703125
,即使结果应该是
3001953125
。 这似乎是因为表达式树看起来像
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();
}

维基百科页面包含以下备注:

^
从右向左求值

我认为您的代码没有考虑到这一点,
^
与其他运算符一样,被视为左关联运算符

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

x^2^3
=>
x^(2^3)
=>
x23^


您的代码和原始答案(30001220703125)是正确的。

维基百科页面包含以下备注:

^
从右向左求值

我认为您的代码没有考虑到这一点,
^
与其他运算符一样,被视为左关联运算符

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

x^2^3
=>
x^(2^3)
=>
x23^



您的代码和原始答案(30001220703125)是正确的。

是的,我以中缀形式编写了这个示例,以说明我希望二元表达式树是什么样子。代码显示了我是如何用后缀符号构建树的。然后,您似乎忽略了导致错误的代码。您能为示例添加后缀吗?我已经为表达式添加了后缀。和维基百科的例子一样,所以我想我可以排除错误。我删除了那个评论,我假设是从左到右。不。只是想让我的记忆恢复一点。我已经很久没有读过这些了……是的,我以中缀的形式写了这个例子,以阐明我希望二元表达式树是什么样子。代码显示了我是如何用后缀符号构建树的。然后,您似乎忽略了导致错误的代码。您能为示例添加后缀吗?我已经为表达式添加了后缀。和维基百科的例子一样,所以我想我可以排除错误。我删除了那个评论,我假设是从左到右。不。只是想让我的记忆恢复一点。我已经很久没有读到这一切了…问题是我如何考虑到这一点。我理解。如果我用C#like double value=3+4*2/(1-5)^2^3(参见第一个单元测试)声明一个变量,我将得到3001953125,而不是30001220703125。我记得学校里不同的计算器对表达式的解释不同。也许也是这样?关于单元测试:
3+4*2/(1-5)^2^3
没有进行任何幂运算<代码>^是唯一的或。事实上,
预期的
将是一个
int
。尽量避免使用
var
,输入常量双精度的
2.0
。我尝试使用
double expected=3.0D+4.0D*2.0D/(1.0D-5.0D)^2.0D^3.0D
,但结果相同。还是我误解了你?
^3.0D
甚至不应该编译。C#中没有Exp/Power运算符,因此很难与C#语法进行比较。问题是我如何考虑这一点。我理解。如果我用C#like double value=3+4*2/(1-5)^2^3(参见第一个单元测试)声明一个变量,我将得到3001953125,而不是30001220703125。我记得学校里不同的计算器对表达式的解释不同。也许也是这样?关于单元测试:
3+4*2/(1-5)^2^3
没有进行任何幂运算<代码>^是唯一的或。事实上,
预期的
将是一个
int
。尽量避免使用
var
,输入常量双精度的
2.0
。我尝试使用
double expected=3.0D+4.0D*2.0D/(1.0D-5.0D)^2.0D^3.0D
,但结果相同。还是我误解了你?
^3.0D
甚至不应该编译。C#中没有Exp/Power运算符,因此很难与C#语法进行比较。
[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
}