对于四则运算表达式,中缀表达式是方便人类读懂的书写方式,而要转化为计算机方便计算的形式必须将其转换为前缀或者后缀表达式。
本文利用栈结构简单数学四则运算表达式的计算,其中仅考虑四则运算和( ),同时不考虑错误表达式的排查。
def RPN_express(m):
"""
构造一个数字栈和一个符号栈,符号栈在如下情况下弹出压入数字栈:
(1)遇到')',将'('之间的四则符号弹出
(2)每一个四则符号压入前,符号栈内等级更高的符号需弹出
@param: m 数学表达式中缀字符串
@return: 数学表达式后缀字符串
"""
weights = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
number_stack = []
symbol_stack = []
for i in m:
if i in '0123456789':
number_stack.append(i) # 压入数字栈
elif i == '(':
symbol_stack.append(i)
elif i in weights:
while symbol_stack and weights[symbol_stack[-1]] >= weights[i]: # 若符号栈为非空
number_stack.append(symbol_stack.pop())
symbol_stack.append(i)
elif i == ')':
while symbol_stack and symbol_stack[-1] != '(':
number_stack.append(symbol_stack.pop())
else:
symbol_stack.pop()
while symbol_stack:
number_stack.append(symbol_stack.pop())
return ' '.join(number_stack)
def RPN_calculate(m):
"""
构造一个数字栈和一个符号栈,数字和符号分别压入其中。按照如下计算规则:
(1)当取得符号,且数字栈倒数两个为数字时,弹出这两个数字,将三者计算,并将结果压入数字栈内
(2)当取得符号,且数字长度不足2时,压入符号栈
(3)最后检查符号栈和数字栈,若符号栈仍有多余,一次进行弹出两个数字+一个字符的计算,再将结果压入数字栈
@param: m 数学表达式后缀字符串
@return: 计算结果
"""
number_stack = []
symbol_stack = []
for i in m.split():
if i in '0123456789':
number_stack.append(i)
elif i in '+-*/':
if len(number_stack) >= 2:
tmp = math_op(number_stack.pop(), number_stack.pop(), i)
number_stack.append(tmp)
else:
symbol_stack.append(i)
while symbol_stack:
tmp = math_op(number_stack.pop(), number_stack.pop(), symbol_stack.pop())
number_stack.append(tmp)
assert len(number_stack) == 1
return number_stack[0]
if __name__ == '__main__':
string = '(1-4*7+3*(6/3+1))/2'
print(RPN_express(string))
print(RPN_calculate(RPN_express(string)))