利用堆栈方式,入栈出栈&运算符运算等级,进行计算; 同一级的运算符,递归计算完,作为一个整体,压入栈;如此反复;按照运算优先级递增的顺序压栈,如果出现非此顺序计算符,则将原来的运算符&数字出栈计算,结果再压栈;
# ELEMENT=['+','-','*','/']
import re
LEVEL_1=['+','-']
LEVEL_2=['*','/']
LEVEL_3=['(']
LEVEL_4=[')']
def is_symbol(element):
if element in LEVEL_1+LEVEL_2+LEVEL_3:
return True
return False
def priority(top_sym,wait_sym):
if top_sym in LEVEL_1:
if wait_sym in LEVEL_1:
return '>'
else:
return '<'
elif top_sym in LEVEL_2:
if wait_sym in LEVEL_2:
return '>'
elif wait_sym in LEVEL_3:
return '<'
elif wait_sym in LEVEL_1:
return '>'
else:
raise ValueError('impossible')
elif top_sym in LEVEL_3:
if wait_sym in LEVEL_4:
return '='
else:
return '<'
def calculate(num1,sym1,num2):
if sym1=='+':
return num1+num2
elif sym1=='-':
return num1-num2
elif sym1=='*':
return num1*num2
elif sym1=='/':
return num1/num2
def init_action(expression):
expression_l=[]
neg_pattern=re.compile('(\-\d+\.*\d*)')
# init_l=[i for i in re.split('(\-\d+\.*\d*)',expression) if i] ##?? 为何要根据 -\d 进行切分
expressions=neg_pattern.split(expression)
expressions=[elem for elem in expressions if elem]
for expression_iter in expressions:
if len(expression_l)==0 and neg_pattern.search(expression_iter):
expression_l.append(expression_iter)
continue
cur_elems=[]
expression_iter=list(expression_iter)
tmp_nums=[]
while len(expression_iter)>0:
iter_elem=expression_iter.pop(0)
if iter_elem in LEVEL_1+LEVEL_2+LEVEL_3+LEVEL_4:
if tmp_nums:
cur_elems.append(float(''.join(tmp_nums)))
tmp_nums=[]
cur_elems.append(iter_elem)
else:
tmp_nums.append(iter_elem)
if tmp_nums:
cur_elems.append(float(''.join(tmp_nums)))
expression_l.extend(cur_elems)
for char_iter in expression_iter:
expression_l.append(char_iter)
return expression_l
def main(expression):
expression_l=init_action(expression=expression)
symbol_stack=[]
number_stack=[]
for index,elem_iter in enumerate(expression_l):
# elem_iter=expression_l.pop(0)
if not is_symbol(elem_iter) and index!=(len(expression_l)-1):
number_stack.append(float(elem_iter))
continue
if not is_symbol(elem_iter) and index == (len(expression_l) - 1):
number_stack.append(float(elem_iter))
if len(symbol_stack)==0:
symbol_stack.append(elem_iter)
continue
while True:
if len(symbol_stack)==0:
break
# top_sym=symbol_stack.pop()
if index==(len(expression_l)-1) and len(symbol_stack)>0:
priority_symbol='>'
elif len(symbol_stack)==0:
break
else:
priority_symbol=priority(top_sym=symbol_stack[-1],wait_sym=elem_iter)
if priority_symbol=='<':
# symbol_stack.append(elem_iter)
break
elif priority_symbol=='>':
right_number=number_stack.pop()
left_number=number_stack.pop()
# right_number=expression_l.pop())
calc_symbol=symbol_stack.pop()
new_num=calculate(num1=left_number,sym1=calc_symbol,num2=right_number)
number_stack.append(new_num)
# symbol_stack.pop()
# symbol_stack.append(top_sym)
elif priority_symbol=='=':
raise ValueError('还没有处理')
else:
raise ValueError('**********ERROR**********')
symbol_stack.append(elem_iter)
if len(number_stack)==1:
print(number_stack)
elif len(number_stack)==2 and len(symbol_stack)==1:
final_number=calculate(number_stack[0],symbol_stack.pop(),number_stack[1])
print(final_number)
else:
print(number_stack)
raise ValueError('what??')
if __name__=='__main__':
a='5+6*4*3-10'
main(expression=a)
# print(r)
将加减乘除括号乘方表达式,建立二叉树, 数字作为叶子节点,终止计算,运算符号作为中间节点;优先级低的在最上层一层,其次是优先级高的在下面一层,进行结合;括号在最上面一层进行结合;因为是pre-order遍历&运算符在上&数字在下,所以 运算符&数字可以分开存储,然后进行concat;
from typing import List
priority={
'+':0,
'-':0,
'*':1,
'/':1
}
def from_infix_to_prefix(expression:List):
res=[]
st=[]
expression.reverse()
for elem in expression:
if elem in [')']:
st.append(elem)
elif elem in ['(']:
last_sym=st.pop()
while last_sym!=')':
res.append(last_sym)
last_sym=st.pop()
elif elem in priority:
# if len(st)>0 and priority[elem]<priority[st[-1]]:
while len(st)>0 and st[-1] not in [")", "]"] and priority[elem]<priority[st[-1]]:
res.append(st.pop())
st.append(elem)
else:
res.append(elem)
while st:
res.append(st.pop())
res.reverse()
print(res)
return res
if __name__=='__main__':
expression = '4+5*6*2-8*7-10'
expression = ['4', '+', '5', '*', '6', '*', '2', '-', '8', '*', '7', '-', '10']
expression='4+5*6*(2-8)*7-10'
expression=['4','+','5','*','6','*','(','2','-','8',')','*','7','-','10']
from_infix_to_prefix(expression=expression)
应用:对数学表达式进行固化表达,同一套表达逻辑;得到整体的embedding表达; 二叉树可以代表一种运算的优先级,底层优先级高,上层优先级低; 二叉树视为多个&多层二叉树的叠加累积,所以可以根据计算优先级,进行分块处理;
本文介绍了如何使用堆栈计算方法处理数学表达式,遵循运算符优先级,递归计算并压栈。同时,通过构建二叉树来表示加减乘除、括号和乘方,利用前序遍历来分离运算符和数字,实现数学表达式的固化和embedding表示。二叉树结构揭示了运算优先级,便于按优先级分块处理。
3281

被折叠的 条评论
为什么被折叠?



