我想编写一个函数来评估作为列表传递的后缀表达式。到目前为止我有:
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
(以symbol
开头)转换为string
,而不是检查int
是否在0到9之间。如果成功,您可以将symbol
视为操作数。 (这允许您的代码处理多位数字。)
更改#2:如果在text
中出现非数字非运算符,则引发错误。 (你不希望其他任何东西在那里。)
改变#3:使用eval
而不是写出每个运算符。 eval
带来了许多安全问题,但我想在这里,因为我们确保一切都是数字或操作员,我们没关系。
更改#4:将中间结果推入堆栈。
更改#5:列表用完后返回s.pop()
。您可能需要添加一行来确认s
此时只包含一个值。
警告:请注意,此代码假定每次遇到运算符时s
将包含两个值。如果对于另一个try
/ except
语句对,则可能需要捕获将引发的错误。
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为您的问题提供了一个非常详细的答案,但我认为有一个错误,虽然我承认我不是这个主题的专家。
由于你使用pop,你的计算就是这样的。 (堆栈中的最后一个数字)(运算符)(堆栈中的倒数第二个),例如,如果列表中有[“3”,“2”,“+”],则得到3 + 2
这对于加法或乘法是好的,但是如果你采用除法或减法,这将导致错误的答案。例如(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()