中缀表达式转化为后缀表达式及计算
不扯别的了,开门见山!我们都见过一般的数学等式,如 ( 9 + ( 3 − 1 ) ∗ 3 + 10 / 2 ) ∗ 7 ( ∗ ) (9+(3-1)*3+10/2)*7 \quad (*) (9+(3−1)∗3+10/2)∗7(∗),计算机是如何快速识别进行计算并得到结果的呢?若我的文章给你有所帮助可以关注一波,感谢感谢!
中缀表达式转化为后缀表达式
这里不再过多的介绍什么是后缀表达式了,不清楚的话点击后缀表达式,利用栈进行转变是一个很好的选择,指针i
从左到右依次读取数据记为loc
,这里需要到一个字典pref = {'+':1,'-':1,'*':2,'/':2,'^':3}
来储存运算符的优先级;一个空字符l
来储存生成的后缀表达式;一个列表A
来暂时储存运算符及括号。对于列表A
的操作规则如下:
- 若
loc
是数字,此时的看后续有没有连续的数字(我们知道连续在一起的数字是一个数,比如(*)式中的10,这里设置一个while循环,终止条件为(指针i
到中缀表达式的最后一个字符或者指针i所指的字符不再是数字) - 若
loc
是非数字,转到3-7 - 若
A
[]或者loc
’('时loc
直接入栈 - 若
loc
==’)’,由于括号内的运算优先级更高,所以将A中栈顶的元素依次输出直到把对应的第一个***‘(’***输出; - 若栈顶的元素直接是’(’,那当前的元素
loc
直接入栈,不可(和)之间没有运算符,这样这对括号是浪费的,也可以在这多一个判断 - 否则就是当前元素和栈顶元素都是运算符,此时比较优先级;若当前元素的优先级>栈顶元素,当前的运算符直接入栈;否则,
A
依次输出直至栈顶的运算符的优先级<当前元素的优先级, - 当前元素入栈
A
- 判断中缀表达式是否被遍历结束,否则回到1.
- 将
A
中的运算符依次从栈顶输出直至为空栈
注意:我们在储存后缀表达式的时候每个数字与运算符之间,数字与数字之间都以空格进行分割。
如以上(*)转变为后缀表达时候的结果为:(9+(3-1)*3+10/2)*7 -->9 3 1 - 3 * + 10 2 / + 7 *
后缀表达式进行式子计算
我们仍用l
表示后缀表达式,为进行计算我们需要一个空栈A
,规则如下:
- 根据空格分隔,若当前遍历的字符时数字,则继续遍历添加读取一个完整的数
loc
直至遍历到空格或者运算符,将此数loc
进栈; - 否则遍历的当前字符就是运算符,此时栈
A
内定有2个以上的元素(否则后缀表达式有问题),将栈顶的两个元素依次输出,
注意:若区分前后顺序的运算,如减法-
,除法/
,乘方^
,此时要主要那个是第一个元素,当时是栈顶的是第一个元素呀(栈的特点啊,先进后出,该复习了哦) - 计算得到的结果在入栈
A
; - 判断后缀表达式是否被遍历结束,否则回到1.
- 栈
A
剩余的一个元素就是中缀表达式的结果。
以上的后缀表达式的A
的逐步结果:
python程序实现
此程序中建立了一个类别为calculate
,里面包含了三个计算函数,及一个__init__
来直接根据已有的中缀表达式生成此类,三个计算函数分别为:
mid_to_aft:
将中缀表达式转化为后缀表达式l
;aft_to_cal:
有参数l
,将后缀表达式进行计算;mid_to_cal:
直接将中缀表达式进行计算。
如有需要可以在自己添加,觉得有用可以收藏一波emmm!
class calculate():
def __init__(self,equ):
self.s = equ
def mid_to_aft(self):
pref = {'+':1,'-':1,'*':2,'/':2,'^':3}
l = ''
A = []
i = 0
while True:
loc = self.s[i]
#可能是一个两位以上的数字
if loc in list('0123456789'):
while i <len(self.s)-1 and self.s[i+1] in list('0123456789'): #不是最后一个数字且为连续数字
loc += self.s[i+1]
i+=1#刚好到连续的最后一个数字
l = l+loc+' '
elif loc in list('()+-*/^'):
if A == [] or loc == '(':
A.append(loc)
elif loc == ')':
while A[-1] != '(':
l =l+ A.pop()+ ' '
A.pop()
elif A[-1] =='(':
A.append(loc)
else:
if pref[loc] > pref[A[-1]]:
A.append(loc)
else:
while A[-1] != '(':
l = l+ A.pop()+ ' '
if A == []:
break
A.append(loc)
i +=1
if i ==len(self.s):
while A!= []:
if len(A) == 1:
l += A.pop()
else:
l =l+ A.pop()+' '
break
return l
def aft_to_cal(self,l):
A = []
i = 0
while True:
print('第{}个元素:A = '.format(i+1),A)
loc = l[i]
if loc in list('0123456789'):
while l[i+1] in list('0123456789'): #此时肯定是数字
loc += l[i+1]
i = i+1
A.append(float(loc))
i+=1
elif loc == ' ':
i+=1
continue
else:
if loc =='+':
A.append(A.pop()+A.pop())
elif loc == '-':
A.append(-A.pop()+A.pop())
elif loc == '*':
A.append(A.pop()*A.pop())
elif loc == '/':
A.append((1/A.pop())*A.pop())
else:
last = A.pop()
A.append(pow(A.pop(),last))
i+=1
if i >= len(l)-1:
break
result = A.pop()
print(l,'=',result)
return result
def mid_to_cal(self):
pref = {'+':1,'-':1,'*':2,'/':2,'^':3}
l = ''
A = []
i = 0
while True:
loc = self.s[i]
#可能是一个两位以上的数字
if loc in list('0123456789'):
while i <len(self.s)-1 and self.s[i+1] in list('0123456789'): #不是最后一个数字且为连续数字
loc += self.s[i+1]
i+=1#刚好到连续的最后一个数字
l = l+loc+' '
elif loc in list('()+-*/^'):
if A == [] or loc == '(':
A.append(loc)
elif loc == ')':
while A[-1] != '(':
l =l+ A.pop()+ ' '
A.pop()
elif A[-1] =='(':
A.append(loc)
else:
if pref[loc] > pref[A[-1]]:
A.append(loc)
else:
while A[-1] != '(':
l = l+ A.pop()+ ' '
if A == []:
break
A.append(loc)
i +=1
if i ==len(self.s):
while A!= []:
if len(A) == 1:
l += A.pop()
else:
l =l+ A.pop()+' '
break
i = 0
while True:
loc = l[i]
if loc in list('0123456789'):
while l[i+1] in list('0123456789'): #此时肯定是数字
loc += l[i+1]
i = i+1
A.append(float(loc))
i+=1
elif loc == ' ':
i+=1
continue
else:
if loc =='+':
A.append(A.pop()+A.pop())
elif loc == '-':
A.append(-A.pop()+A.pop())
elif loc == '*':
A.append(A.pop()*A.pop())
elif loc == '/':
A.append((1/A.pop())*A.pop())
else:
last = A.pop()
A.append(pow(A.pop(),last))
i+=1
if i >= len(l)-1:
break
result = A.pop()
print(l,'=',result)
return result