思路:
數學計算式是中綴表達式,所以先把中綴表達式轉換爲後綴表達式,然後對後綴表達式進行求值。
中綴表達式: 在通常的表達式中,二元運算符總是置於與之相關的兩個運算對象之間,這種表示法也稱爲中綴表達式
後綴表達式: 又叫逆波蘭表達式 ,不包含括號,運算符放在兩個運算對象的後面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則,如:(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