如何计算前缀表示法中的表达式
我正在尝试评估一个以前缀表示法表示表达式的列表。以下是此类列表的示例:
[+, [sin, 3], [- 10 5]]
评估列表价值的最佳方法是什么
I am trying to evaluate a list that represents an expression in prefix notation. Here is an example of such a list:
[+, [sin, 3], [- 10 5]]
What is the best way to evaluate the value of the list
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果使用后缀而不是前缀,会更简单。请参阅逆波兰表示法 (RPN)。给定 RPN 中的一个表达式,只需使用一个堆栈即可轻松计算该表达式。
但是,由于您要求一种无需递归和使用堆栈来评估前缀表达式的方法(对于可能更简单的方法,请参阅下面的编辑:下面),这是一种方法:
我们可以使用两个堆栈来做到这一点。
一个堆栈(称为求值)保存运算符(如 +、sin 等)和操作数(如 3,4 等),另一个堆栈(称为计数)保存剩余可见操作数数量 + 数字的元组运算符期望的操作数。
每当您看到运算符时,都可以将该运算符推入计算堆栈,并将相应的元组推入计数堆栈。
每当您看到操作数(例如 3,5 等)时,您都会检查计数堆栈的顶部元组并减少该元组中剩余的操作数数量。
如果剩余可见操作数的数量变为零,则从计数堆栈中弹出该元组。然后从计算堆栈中弹出所需的操作数数量(您知道这一点是因为元组的其他值),弹出运算符并执行操作以获得新值(或操作数)。
现在将新操作数推回到计算堆栈上。这个新的操作数推送使您再次查看计数堆栈的顶部,并且执行我们刚才所做的相同操作(减少看到的操作数,与零进行比较等)。
如果操作数计数未变为零,则继续输入中的下一个标记。
例如,假设您必须评估 + 3 + 4 / 20 4
堆栈看起来像(左侧是堆栈的顶部)
编辑:
一位朋友建议了一种无需多个堆栈即可执行此操作的方法:
从末尾开始,转到第一个操作员。其右侧的标记将是操作数。评估并重做。看起来比用两个堆栈简单得多。我们可以使用双向链表来表示我们在处理过程中更改的输入。计算时,删除节点,然后插入结果。或者您也可以只使用一个堆栈。
It will be simpler if you used postfix instead of prefix. See Reverse Polish Notation (RPN). Given an expression in RPN, it is easy to evaluate that using just one stack.
But since you asked for a way to evaluate prefix expressions without recursion and using stacks (for a possibly simpler way, see EDIT: below), here is one way:
We can do this using two stacks.
One stack (call it Evaluation) holds the operators (like +, sin etc) and operands (like 3,4 etc) and the other stack (call it Count) holds a tuple of the number of operands left to be seen + the number of operands an operator expects.
Anytime you see an operator, you push the operator onto the Evaluation stack and push the corresponding tuple onto the Count stack.
Anytime you see an operand (like 3,5 etc), you check the top tuple of the Count stack and decrement the number of operands left to be seen in that tuple.
If the number of operands left to be seen becomes zero, you pop the tuple from the Count stack. Then from the Evaluation stack you pop off the number of operands required (you know this because of the other value of the tuple), pop off the operator and do the operation to get a new value, (or operand).
Now push the new operand back on the Evaluation stack. This new operand push causes you to take another look at the top of the Count stack and you do the same thing we just did (decrement the operands seen, compare with zero etc).
If the operand count does not become zero, you continue with the next token in the input.
For example say you had to evaluate + 3 + 4 / 20 4
The stacks will look like (left is the top of the stack)
EDIT:
A friend suggested a way to do this without multiple stacks:
Start from the end, go to the first operator. The tokens to the right of that will be operands. Evaluate and redo. Seems much simpler than doing it with two stacks. We can use a doubly linked list to represent the input which we change during processing. When you evaluate, you delete nodes, and then insert the result. Or you could perhaps just use one stack.
KISS,作为后缀表达式反向求值。
KISS, evaluate in reverse as a postfix expression.
在我看来,你有两个选择。要么从左到右,要么从右到左(正如保罗上面建议的那样)。下面的代码演示了这两种方法。
一些测试:
The way I see it you have two options. Either go left to right or right to left (as paul suggested above). Both methods are demonstrated in the code below.
Some tests: