一、思路:
计算器:我们要计算一个长的字符串,字符串中包含+、-、*、/、=、[0-9]、();
在这里我们要考虑优先级的问题:
- 有括号先算括号内部的的
- 没有括号,要先算乘除
- 乘除算完之后要进行加减运算
二、
1.没有括号的情况下的加减乘除
s = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
s1 = '9-2*5/3+7/3*-99/4*2998+10*568/14'
#*/的优先级高要先进行计算
#用*或者/对字符串进行分割
m = re.split('(\d+\.?\d*[*/]-?\d+\.?\d*)',s1,1)
#取出内部括号内没有括号的情况
print(m)
#['9-', '2*5', '/3+7/3*-99/4*2998+10*568/14']
if len(m) == 3:
bef = m[0]
con = m[1]#这个就是我们要计算分割出来要进行计算的只含有乘除的式子
aft = m[2]
if '*' in con:
a,b = con.split('*')
c = float(a)*float(b)#这里的c是浮点型
temp = bef + str(c) + aft
s1 = temp
print(s1)#9-10.0/3+7/3*-99/4*2998+10*568/14计算了第一个*两边的数计算的结果并更新了字符串
else:
a, b = con.split('/')
c = float(a) / float(b) # 这里的c是浮点型
temp = bef + str(c) + aft
s1 = temp
print(s1)
2.封装到函数当中
import re
s = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
s1 = '9-2*5/3+7/3*-99/4*2998+10*568/14'
#*/的优先级高要先进行计算#用*或者/对字符串进行分割
def chengchu(s1):
while True:
m = re.split('(\d+\.?\d*[*/]-?\d+\.?\d*)',s1,1)
#取出内部括号内没有括号的情况
# print(m)
if len(m) == 3:
bef = m[0]
con = m[1]#这个就是我们要计算分割出来要进行计算的只含有乘除的式子
aft = m[2]
if '*' in con:
a,b = con.split('*')
c = float(a)*float(b)#这里的c是浮点型
temp = bef + str(c) + aft
s1 = temp
# print(s1)
else:
a, b = con.split('/')
c = float(a) / float(b) # 这里的c是浮点型
temp = bef + str(c) + aft
s1 = temp
# print(s1)
else:
return s1
q = chengchu(s1)
m = eval('9-2*5/3+7/3*-99/4*2998+10*568/14')
print(m)
n = eval('9-3.3333333333333335+-173134.50000000003+405.7142857142857')
print(n)
print(q)
结果:
-172723.11904761908
-172723.11904761908
9-3.3333333333333335+-173134.50000000003+405.7142857142857
三、考虑只有加减的字符串
1.
s = '-1+2-3+5+9-6'
m = re.findall('-?\d+\.?\d*',s)
print(m)#m是一个列表包含很多元素
w = 0
for i in m:#遍历出列表中的所有元素
w = w + float(i)#元素遍历相加
print(w)
结果:
['-1', '2', '-3', '5', '9', '-6']
6.0
2.对函数进行封装
s = '-1+2-3+5+9-6'
def jiajian(s):
m = re.findall('-?\d+\.?\d*',s)
print(m)#m是一个列表包含很多元素
w = 0
for i in m:#遍历出列表中的所有元素
w = w + float(i)#元素遍历相加
# print(w)
return w
a = jiajian(s)
print(a)
结果:
['-1', '2', '-3', '5', '9', '-6']
6.0
四、去括号思路
1.
s = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
s = re.sub('\s*',s)#去除字符串中的空白符
m = re.split('\(([^()]*)\)',s,1)#找到一个不包含括号的算书式
print(m)
结果:
['1-2*((60-30+', '-40.0/5', '*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
注:一次分割之后的到了一个有三个元素的列表,第一个元素就是我们要取的括号内部的内容
五、各个模块的功能已经实现,下面要做的就是“拼图”。
import re
def chengchu(s):
while True:
m = re.split('(\d+\.?\d*[*/]-?\d+\.?\d*)',s,1)#用*、/号对列表进行分割分割之后一共是三部分,如果分割成功m[1]要么包含乘号要么包含除号
if len(m) == 3:
bef = m[0]
con = m[1]
aft = m[2]
# print(con,type(con))
if "*" in con:#如果包含乘号
a,b = con.split('*')#把*号前面的值赋值给a,把*号后面的值赋值给b
c = float(a)*float(b)#c是a与b的乘积
temp = bef + str(c) +aft#把c转换成字符串的格式,将进行乘法运算的字符串重新拼接,
s = temp#将新得到的字符串替换掉原来进行计算的字符串
else:
a, b = con.split('/')#把/号前面的值赋值给a,把*号后面的值赋值给b
c = float(a) / float(b)#c是a与b的商
temp = bef + str(c) + aft#把c转换成字符串的格式,将进行乘法运算的字符串重新拼接,
s = temp#将新得到的字符串替换掉原来进行计算的字符串
else:
return s
def jiajian(s):
# 再计算之前把--、++替换成 +;把+-、-+替换成 - ;
s = re.sub('\-\-', '+', s)
s = re.sub('\-\+', '-', s)
s = re.sub('\+\-', '-', s)
s = re.sub('\+\+', '+', s)
m = re.findall('-?\d+\.?\d*',s)#找到字符串中所有的数字,包含数字前面的符号
w = 0
for i in m:
w = w + float(i)
return w
s = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))--(-4*3)/(16-3*2))'
print(s)
while True:
s = re.sub('\s*','',s) # 去除输入字符串中的空白符
m = re.split('\(([^()]*)\)',s,1)#re.split之后的m是一个列表;遍历字符串依次去除第一个()一直到最后一个
if len(m) == 3:
bef = m[0]
con = m[1]
aft = m[2]
a = chengchu(con) # 先算乘除法
b = jiajian(a) #乘除法计算完之后的算术式就只是含有加减号;调用jiajian函数
#加减计算完成之后b就是一个浮点数
s = bef + str(b) +aft#将字符串重新拼接
print(s)#每一次计算之后输出更新后的新的
else:
#全部的括号去除之后对式子在进行计算:先乘除再加减
a = chengchu(s)#这里计算的表达式是一个单纯的算术式没有括号所以是去掉了括号的s
b = jiajian(a)
print(b)#输出最终的计算结果
break
#用eval来验证计算的是否正确
print(eval('1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))--(-4*3)/(16-3*2))'))
结果:
1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))--(-4*3)/(16-3*2))
1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))--(-4*3)/(16-3*2))
1-2*((60-30+-8.0*173545.88095238098)--(-4*3)/(16-3*2))
1-2*(-1388337.0476190478--(-4*3)/(16-3*2))
1-2*(-1388337.0476190478---12.0/(16-3*2))
1-2*(-1388337.0476190478---12.0/10.0)
1-2*-1388338.2476190478
2776677.4952380955
2776677.4952380955