python判断正负数嵌套_Python学习之函数(多层函数)、re模块的正则匹配--计算复杂加减乘除...

头疼,其实这个程序在我看的视频当中是当做re模块的运用来进行测试的,而到了我这里就成了简化版的了,因为我实在是做吐了,恕小弟无能,只能做简化版的。为何说是简化版呢,因为要求是给的计算式是多层嵌套的小括号“()”,然后计算的时候不能用eval方法,eval是个好东西啊,他能直接得到字符串中的结果,比如eval(“23+34*45/345-34”)=结果,是可以直接给你返回算术式的结果的,如果你自己处理这段字符串的话就要花好多工夫拆解字符串。我的简化版是将多层小括号给分为了小括号“()”、中括号“【】”、大括号“{}”,不允许使用多层相同括号连续嵌套(相应的不允许超过三层,超过三层,小弟无能为力),而我觉得,想要区分不同的层级的小括号“(()())”是需要下功夫用re正则去匹配的,而我这个用是用到正则了,但用的很少,重点全在如何自己写代码实现eval的功能了。

效果图:

1803903-20191120223323767-397286661.png

1803903-20191120223346576-54565981.png

另附一张各步骤计算详解

1803903-20191120223424799-301800387.png

源代码:

import re

def Get_FuH(As):

As = As.replace('--','+')

As = As.replace('+-', '+')

As = As.replace('/-', '/')

As = As.replace('*-', '*')

End = []

As = list(As)

if (As[1] == '-'):

As.pop(1)

for i in As:

if(i == '/' or i == '+' or i == '*' ):

End.append(i)

elif(i == '-'):

End.append('+')

for i in End:

if(i == ''):

End.pop(End.index(''))

return End

def Get_Num(As):

As = As.replace('--', '-')

As = As.replace('+-', '-')

As = As.replace('/-', '-')

As = As.replace('*-', '-')

As = list(As)

Get = []

End = []

for i in As:

if(i <= "9" and i >= "0" or i == '.'):

Get.append(i)

else:

End.append(''.join(Get))

Get = []

if(i == '-'):Get.append(i)

for i in End:

if(i == ''):

End.pop(End.index(''))

for i in End:

if(i == ''):

End.pop(End.index(i))

return End

def Do_Xiao(As):

a = re.findall("\([+\-*/0-9.]*\)",As)

# print(a)

for i in a:

TiH = i

ShuZ = Get_Num(TiH)

FuH = Get_FuH(TiH)

ShuZ_New = []

FuH_New = []

# print(TiH)

# print(ShuZ)

# print(FuH)

for q in FuH:

if (q == '*'):

m = FuH.index('*')

End = float(ShuZ[m]) * float(ShuZ[m + 1])

ShuZ[m] = 0

FuH[m] = 0

ShuZ[m+1] = End

elif (q == '/'):

m = FuH.index('/')

End = float(ShuZ[m]) / float(ShuZ[m + 1])

ShuZ[m] = 0

FuH[m] = 0

ShuZ[m + 1] = End

for i in ShuZ:

if (i != 0): ShuZ_New.append(i)

for i in FuH:

if (i != 0): FuH_New.append(i)

# print(ShuZ_New)

# print(FuH_New)

for i in FuH_New:

if (i == '+'):

n = FuH_New.index('+')

End = float(ShuZ_New[n]) + float(ShuZ_New[n + 1])

ShuZ_New[n] = 0

FuH_New[n] = 0

ShuZ_New[n + 1] = float(End)

elif (i == '-'):

n = FuH_New.index('-')

End = float(ShuZ_New[n]) - float(ShuZ_New[n + 1])

ShuZ_New[n] = 0

FuH_New[n] = 0

ShuZ_New[n + 1] = float(End)

for p in ShuZ_New:

if (p != 0):

As = As.replace(TiH, str(p))

return As

def Do_Zhong(As):

As = As.replace("[","(")

As = As.replace("]",")")

As = Do_Xiao(As)

return As

def Do_Da(As):

As = As.replace("{","(")

As = As.replace("}",")")

# print(As)

As = Do_Xiao(As)

return As

def End_end(As):

As = '(' + As + ')'

End = Do_Xiao(As)

return End

if __name__ == '__main__':

AA = "1-2*{[60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14)]-(-4*3)/(16-3*2)}"

BB = "34+45*{44+34*45+44/45}-{[34*45/44]*(456+466*345-3445/455)}"

As = input("请输入你要计算的式子:")

As = Do_Xiao(As)

print(As)

As = Do_Zhong(As)

print(As)

As = Do_Da(As)

print(As)

End = End_end(As)

print(End)

解析:我的整体思路很简单,就是按顺序一步步提取,先用正则把小括号的内容提取出来,因为有格式要求,所以提取的小括号的内容都是闭合的(即()中间不会出现()或者单边括号,匹配较为容易)。对提取的内容进行处理:定义了几个函数:1、提取数字,我将提取的字符串转为列表,然后把通过运算符分割的数字(之所以取运算符是因为有多位数还有小数点的存在,这样可以将一个数字完整的存放在一起)按个存放到一个列表中。2、提取运算符,直接扫描字符串列表提取即可。3、运算,因为运算符是两个数进行运算,所以通过循环运算符,每一个运算符都是运算符左右两个数的和。为了区分优先级(先乘除后加减),我进行了两边循环符号,且第二遍循环是在第一次的基础上删除了乘除运算符后的列表。即第一遍循环只算乘除,第二遍再算加减。4、中括号转小括号,一定要在小括号运算完,公式中没有小括号才能调用。5、大括号转小括号,同理中括号,因为如果大括号转成小括号,里面还有中括号会卡在中括号上没有匹配符。

再说说中间的遇到的一些bug,也是导致代码混乱的地方,这些我都没来的及优化,测视了两个算术式没问题就不搞了,头疼。1、提取数字,“-”是个大问题,到底把他算在运算符列表中呢还是算在数字列表中呢,我选择的是放在数字中,即数字分正负,由此我需要判断“+-”、“--”、“/-”、“*-”,后两个还好说,前两个真是搞死了,就在那算负负、正正的逻辑去了,还要在表达式中进行替换工作,将双符号进行缩减成标准的单符号传进符号列表中,因为符号列表的数目一旦不对,就会导致数字列表没有匹配正确(这也是最麻烦的地方,中间出了好几次超出列表范围的bug)。另一个问题比较严重的问题是在乘除算完给加减新的列表的时候,因为有连乘连除的存在,所以我需要将计算的结果再存到列比中循环利用,我的方法是算一个弹出一个,既可以继续运行,还可以缩减列表,到最后符号列表为空,数字列表还剩一个结果。呵呵,理想很丰满,结果最大的bug出来了,找了好半天,把所有的循环都输出了一遍才找到原因:因为我是用for循环,通过i in 符号列表,然后当i匹配到运算符,就找到这个下表,然后弹出去这个运算符元素,数字列表弹出去两个数字,但当我符号弹出去这个后,列表索引自动迁移,导致i+1成了i,i+1还没进行循环,就变成了下一次循环到了i+2,简单说就是每一次循环i+1,当我弹出当前位置i后,i(y) = i+1,且这是在本次循环结束前,所以当下一次循环开始时,其实是y+1,也就是上一次循环中的i(i已经被弹出去了,i成了i+1)的后面的后面这个元素,及跳过了一个i的循环,为了避免这种情况,我不弹出元素,而是全都初始化为0,当乘除运算完后,再进行“除0”,即构造新列表再次进行加减运算。

使用说明:大、中、小括号必须数目,位置等对称,且不能乱套,中规中举的小中大或者小中、小大、中大,不可小套大。式子中用到那种括号就调用一次对应的函数,且从小往大一层层的调。我没有设检查式子是否合规,讲道理应该不会再出什么问题了,AA的式子是我照着这个写的程序,BB是用来测试的,我只测试了这一个,毕竟长公式写起来也麻烦,自己再在手机上算一遍也麻烦,但AA、BB的式子我都在手机上算过了,都对,且更精确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值