python 表达式求值 abc由用户输入_用Python实现表达式求值,递归解法和栈解法(附详细代码和测试)...

问题描述:

输入四则运算表达式,仅由数字、+、-、*、/、()组成,没有空格,要求求其值,假设运算符结果都是整数,/结果也是整数

输入:

(2+3)*(5+7)+9/3

输出:

63

第一种解法:eval()函数

>>> eval('(3+5)*2')

16

第二种解法:递归

搞清楚表达式的递归定义很关键

表达式=项或项的加减项=因子或因子的乘除因子=(表达式)或整数

代码:

def expression_value():

global i

a=term_value()

if i==len(s):

return a

c=s[i]

while c in '+-':

i+=1

b=term_value()

if c=='+':

a+=b

else:

a-=b

if i==len(s):

return a

else:

c=s[i]

if c==')':

i+=1

return a

return a

def term_value():

global i

a=factor_value()

if i==len(s):

return a

c=s[i]

while c in '*/':

i+=1

b=term_value()

if c=='*':

a*=b

else:

a=a//b

if i==len(s):

return a

else:

c=s[i]

return a

def factor_value():

global i

if s[i]=='(':

i+=1

return expression_value()

else:

temp_i=i

while s[i].isdigit():

i+=1

if i==len(s):

break

return int(s[temp_i:i])

s='(((3+2)*2-8)-8)*3+20'

i=0

print(expression_value())

输出为2,正确

但是这种做法有个bug,就是把没必要加括号的加了括号就会只计算括号里的 比如(8/4)-6得到2,但是8/4-6得到-4,此bug留待有缘再来破。。。

第三种解法:栈

中缀表达式转后缀表达式(栈存放操作符)计算后缀表达式的值(栈存放数)

中缀转后缀的规则:(这里借鉴自csdn的某位作者)

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

上代码,其中中缀转后缀的函数是参考这个规则写的,感觉还挺麻烦,写了快一个小时。不过最后的结果还是感到舒适。

def infix2suffix(s):

l=[]

out=[]

i=0

while i

if s[i].isdigit():

temp_i=i

while  i

i+=1

out.append(int(s[temp_i:i]))

i-=1

if i==len(s)-1:

for t in l[::-1]:

out.append(t)

break

else:

if i==len(s)-1:

for t in l[::-1]:

out.append(t)

break

if s[i]=='(':

l.append('(')

elif s[i]==')':

while True:

p=l.pop()

if p=='(':

break

else:

out.append(p)

elif s[i] in '*/':

if len(l)==0:

l.append(s[i])

else:

while True:

if len(l)==0:

break

p=l.pop()

if p in '(+-':

l.append(p)

break

else:

out.append(p)

l.append(s[i])

elif s[i] in '+-':

if len(l)==0:

l.append(s[i])

else:

while True:

if len(l)==0:

break

p=l.pop()

if p=='(':

l.append(p)

break

else:

out.append(p)

l.append(s[i])

i+=1

if '(' in out:

out.remove('(')

return out

def suffix2result(lst):

l=[]

for i in lst:

if isinstance(i,int):

l.append(i)

else:

a=l.pop()

b=l.pop()

if i=='+':

l.append(b+a)

elif i=='-':

l.append(b-a)

elif i=='*':

l.append(b*a)

else:

l.append(b//a)

return l.pop()

l=infix2suffix('(2+3)*(5+7)+9/3-((8/4)-6)')

print(l)

print(suffix2result(l))

输出:

> [2, 3, '+', 5, 7, '+', '*', 9, 3, '/', '+', 8, 4, '/', 6, '-', '-']

> 67

这种做法就很好了,无论怎么加括号都会得到正确的逆波兰表达式和结果。

中缀转后缀用到的栈存放符号,根据一系列规则生成正确的后缀表达式。后缀表达式求值用到的栈存放数,这个过程就很简单了。

最后要问的是有没有人知道递归解法我的代码哪里出了bug?请在下面留言,感激不尽~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值