思路:
数学计算式是中缀表达式,所以先把中缀表达式转换为后缀表达式,然后对后缀表达式进行求值。
中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式
后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *
构造栈
class Stack():
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item): # 入栈
self.items.insert(0, item)
def pop(self): # 出栈
return self.items.pop(0)
def peek(self): # 取栈顶元素
return self.items[0]
def size(self): # 栈的长度
return len(self.items)
中缀表达式转后缀表达式
import re
def infixToPostfix(infixer):
# 建立运算符优先级字典
proc = {'/': 3,
'*': 3,
'+': 2,
'-': 2,
'(': 1}
opStack = Stack()
postList = []
# tokenList = infixer.split()
tokenList = re.findall('[\+\-\*\/\(\)]|[\d]+', infixer) # 使用正则表达式解析公式
for token in tokenList:
if re.match('\d+', token): # 如果是数字先把数字先放入输出结果的列表
postList.append(token)
elif token == '(': # 如果是“(”放入栈中
opStack.push(token)
elif token == ")": # 如果遇到 “)”出栈
topToken = opStack.pop()
while topToken != "(": # 如果弹出的元素不是 “(”
postList.append(topToken) # 把 “*/+-” 放入输出结果列表
topToken = opStack.pop() # 弹出栈中的值
else:
while not opStack.isEmpty() and (proc[opStack.peek()] > proc[token]):
# 如果栈不为空且栈顶的的元素优先级大于token, 弹出栈顶元素并写入结果输出列表
postList.append(opStack.pop())
opStack.push(token) # 把 token push 进栈
while not opStack.isEmpty(): # 如果栈不为空, 把栈里的元素都弹出输出到列表
postList.append(opStack.pop())
return postList
def expression_to_value(expression):
stack_value = []
for item in expression: #遍历后缀表达式元素
if item in ["+", "-", "*", "/"]: # 如果是运算符, 弹出列表中最后的两个元素
n1 = stack_value.pop()
n2 = stack_value.pop()
result_value = calc(n1, n2, item) # 调用计算函数
stack_value.append(result_value) # 计算结果添加到列表
else:
stack_value.append(int(item)) # 计算结果添加到列表末端
return stack_value[0]
def calc(n1, n2, op):
if op == '+':
return n1 + n2
if op == '-':
return n2 - n1
if op == '*':
return n1 * n2
if op == '/':
return n2 / n1