在python中评估后缀?
我想写一个函数来计算作为列表传递的后缀表达式。到目前为止,我得到了:在python中评估后缀?,python,postfix-notation,Python,Postfix Notation,我想写一个函数来计算作为列表传递的后缀表达式。到目前为止,我得到了: def evalPostfix(text): s = Stack() for symbol in text: if symbol in "0123456789": s.push(int(symbol)) if not s.is_empty(): if symbol == "+": plus = s.p
def evalPostfix(text):
s = Stack()
for symbol in text:
if symbol in "0123456789":
s.push(int(symbol))
if not s.is_empty():
if symbol == "+":
plus = s.pop() + s.pop()
if symbol == "-":
plus = s.pop() - s.pop()
if symbol == "*":
plus = s.pop() * s.pop()
if symbol == "/":
plus = s.pop() / s.pop()
但我认为我的方法是错误的。帮助?您有一些问题:
def eval_postfix(text):
s = list()
for symbol in text:
if symbol in "0123456789":
s.append(int(symbol))
plus = None
elif not s.is_empty():
if symbol == "+":
plus = s.pop() + s.pop()
elif symbol == "-":
plus = s.pop() - s.pop()
elif symbol == "*":
plus = s.pop() * s.pop()
elif symbol == "/":
plus = s.pop() / s.pop()
if plus is not None:
s.append(plus)
else:
raise Exception("unknown value %s"%symbol)
return s.pop()
这里有一个可能对您有用的解决方案。我试着尽可能少地修改你的代码 更改#1:与其检查
symbol
是否介于0和9之间,不如尝试将symbol
(以字符串开始)转换为int
。如果成功,您可以将symbol
视为操作数。(这允许您的代码处理多位数。)
更改#2:如果文本
中出现非数字、非运算符,则引发错误。(你不希望里面还有其他东西。)
更改#3:使用eval
而不是写出每个运算符<代码>评估
带来了很多安全问题,但我认为在这里,因为我们确保所有东西都是数字或操作员,所以我们没事
更改#4:将中间结果推入堆栈
更改#5:在列表用尽后返回s.pop()
。您可能需要添加一行,确认此时s
仅包含一个值
注意:请注意,此代码假定每次遇到运算符时,s
将包含两个值。如果另一对try
/语句出现错误,您可能希望捕获该错误
def evalPostfix(text):
s = Stack()
for symbol in text:
try:
result = int(symbol)
except ValueError:
if symbol not in '+-*/':
raise ValueError('text must contain only numbers and operators')
result = eval('%d %s %d' % (s.pop(), symbol, s.pop()))
s.push(result)
return s.pop()
Hosane为你的问题提供了一个非常详细的答案,但是我认为我看到了一个错误,尽管我承认我不是这方面的专家
因为你用的是流行音乐,所以你的计算是这样的。
(堆栈中的最后一个数字)(运算符)(堆栈中的第二个最后一个数字)
例如,如果列表中有[“3”、“2”、“+”],则得到3+2
这对于加法或乘法都很好,但是如果你使用除法或减法,这将导致错误的答案。例如,postfix中的(3-2)将是[3,2,-]。您的代码会将其计算为(2-3),而它应该是(3-2)
所以你应该改变除法和减法,如果情况是
elif symbol=="-":
s.append(-stack.pop() + stack.pop())
elif symbol=="/":
s.append(1/stack.pop() * stack.pop())
翻译K&R C示例的工作代码
def eval_postfix(text):
stack = []
tokens = text.split(" ")
for token in tokens:
if token.strip() == '':
continue
elif token == "+":
stack.append(stack.pop() + stack.pop())
elif token == "-":
op2 = stack.pop()
stack.append(stack.pop() - op2)
elif token == '*':
stack.append(stack.pop() * stack.pop())
elif token == '/':
op2 = stack.pop()
if op2 != 0.0:
stack.append(stack.pop() / op2)
else:
raise ValueError("division by zero found!")
elif (is_number(token)):
stack.append(float(token))
else:
raise ValueError("unknown token {0}".format(token))
return stack.pop()
现在这个函数不返回任何内容。什么是堆栈
,推送
做什么?为什么您认为这种方法是错误的?@dbliss我使用的是堆栈(抽象数据类型)并且有一个类使用push和pop方法从堆栈中添加/删除元素。@Stefan Pochmann主要是因为我不确定如何返回正确的值。如果只有两个操作数,并且它们始终是单位数,那么我认为您现在的操作数是有效的。只需返回plus
。很好。你的回答让我意识到中间结果应该被推到堆栈上。我的答案正确吗?您是否切换到列表
,以便您和其他人可以测试它?您可以使用类堆栈(list):push=list.append
。只是说因为我喜欢你尽量不做太多的改变。是的,但基本上我在过去几年一直使用列表作为堆栈。但是,您的建议使代码更具可读性。:)我认为OP的push
可能会像append
那样将项目添加到堆栈的前端,而不是末尾。OP没有指定,所以我们不能确定。是的,push会将项目添加到列表的前面,我使用堆栈是因为您无法将append方法用于堆栈,但是在列表上使用append方法也可以,非常感谢@HosaneI我认为“我已尝试尽可能少地更改您的代码”是一个谎言:-PHa,是的,这是我一开始的目标,不管怎样,我真的不喜欢例外的方法。您还可以使用symbol.isdigit()方法来确定是否只讨论单字符数字(这里就是这种情况)。eval
在这里,因为eval
在任何地方都是一个坏主意。而且,即使eval
是合理的,使用Python的解析器计算算术也完全没有从零开始编写表达式计算器的意义。