正则计算器版中版之最后一版!
作业要求是用正则编写一个计算器,可以计算长公司的计算器
1 # # coding=utf-8 2 # 1,开始入口,写一个formula,直接调用运算方法calc() 3 # 2,首先要去括号,先调用一个while循环的方法,正则方法找出最里层的括号,然后再str方法去括号,将结果进行乘除法计算 4 # 3,乘除法计算,这个乘除法要在上边的while循环里边进行,运费处理掉括号后的formula 5 # 4,先用正则分割的方法,用加减号分割,然后进行去分母去负号。 6 # 5,分母去负号方法:新建一个列表,循环老列表的值有序号,如果最后一个字母是*/,就将他与他后边的数字相‘连’,为了相连,前边要进行str方法。 7 # 把其他的含有*/的字符串,都放到新列表里,这样就形成了一个只有乘除法的列表,且分母可以是负数。返回这个新的列表 8 9 # 6,循环这个列表,把每个元素单独计算,先用split方法进行分割,再用finall方法,找出运算符。 10 # 7,循环分割的元素列表,声明一个运算结果,把第一个元素赋值给第一个结果,然后进行后边的运算,如果运算符是乘号,就进行乘法运算。 11 # 8,将运算结果替换运算公式。进行加减运算。 12 # 9.进行加减运算之前,先把所有运算符进行替换。替换后用+—进行分割,在找出所有加减号 13 # 10,跟乘法一样,先声明一个结果为空,然后如果不为空就进行运算,为空就赋值。运算过程出现加号就加,最后输出结果 14 import re 15 def jiajian(formula): 16 print(formula,'未进行加减号替换运算符的formula') 17 formula=formula.replace('--','+') 18 formula=formula.replace('+-','-') 19 formula=formula.replace('-+','-') 20 formula=formula.replace('++','+') 21 formula=formula.replace("- -", "+") 22 print(formula,'这里把加减号进行替换后的formula') 23 24 sub_yuansu_list = re.split('[+-]', formula) 25 sub_yunsuanfu_list = re.findall('[+-]', formula) 26 print("元素列表与运算符列表",sub_yuansu_list,sub_yunsuanfu_list) 27 # if sub_yuansu_list[0]=='': 28 # sub_yuansu_list[0]=='0' 29 30 print('!!!!!!!!!!!!!!!!!!!!!!!!!!!') 31 if sub_yuansu_list[0] == '': 32 sub_yuansu_list.remove('') 33 sub_yuansu_list.insert(0, '0') 34 print(sub_yuansu_list) 35 res=None 36 for index,i in enumerate(sub_yuansu_list): 37 if res: 38 if sub_yunsuanfu_list[index-1]=='-': #这里要想清楚,因为这里至少是第二次,第二次-1,那么就是元素列表index的第一次 39 res -= float(i) 40 else: 41 res += float(i) 42 else: 43 res=float(i) 44 print('\033[31;1m[结果^^^%s]\033[0m' %res,'完成加减法运算后的结果') 45 return res 46 47 48 def delet_fuhao_fengmu(formula): 49 new_list=[] 50 print(formula,'测试16/10') 51 for index,item in enumerate(formula): 52 53 if item.strip().endswith('*')or item.strip().endswith('/'): 54 new_list.append('%s-%s'%(formula[index],formula[index+1])) 55 elif '*' in item or '/' in item: 56 57 new_list.append(item) 58 print(new_list) 59 print(new_list,'这里是拼接分母后的列表,保留了需要进行乘法运算的元素') 60 return new_list 61 62 63 64 def chengchu(formula): 65 print('运算',formula) 66 sub_fengge_formula=re.split('[+-]',formula) #用加减号分割 67 print(sub_fengge_formula,'乘法接口还没进入del符号') 68 sub_fengge_formula = delet_fuhao_fengmu(sub_fengge_formula) 69 for index,item in enumerate(sub_fengge_formula): 70 sub_yuansu_list = re.split('[*/]',item) 71 sub_yunsuanfu_list = re.findall('[*/]',item) 72 print('乘除里打印两个列表',sub_yuansu_list,sub_yunsuanfu_list) 73 sub_res =None 74 for index,i in enumerate(sub_yuansu_list): 75 if sub_res: 76 if sub_yunsuanfu_list[index-1]=='*': 77 sub_res *= float(i) 78 else: 79 sub_res /= float(i) 80 else: 81 sub_res=float(i) 82 print('\033[31;1m[%s]=\033[0m'%item,sub_res,'这是完成乘法运算的结果') 83 84 formula=formula.replace(item,str(sub_res)) 85 print('\033[31;1m[%s]结果\033[0m'%formula,'这是在乘法里把结果替换为最准值') 86 res_zuihou=jiajian(formula) 87 88 return res_zuihou 89 90 91 def calc(formula): 92 calc_flage = True 93 while calc_flage: 94 95 m=re.search('\([^()]+\)',formula) 96 97 if m: 98 print(m.group(),'正则出最里边的括号') 99 sub_formula = m.group().strip('()') 100 print('去括号后', sub_formula) 101 sub_res = chengchu(sub_formula) 102 print(sub_res,'完成一次运算后的值') 103 104 formula=formula.replace(m.group(),str(sub_res)) 105 print(formula,'完成替换后的值') 106 else: 107 print('\033[41;1m----没拓号了...---\033[0m') 108 109 print('\n\n\033[42;1m最终结果:\033[0m', chengchu(formula)) 110 calc_flage = False # 代表公式里的拓号已经都被剥除啦 111 112 113 114 115 if __name__ == '__main__': 116 formula='1-2*(60-30+ (-40.0/5*(9-2*5/-3+7/3*99/4*2998+10*568/14)))-(-4*3)/(16-3*2)' 117 res=calc(formula) 118 119 120 print('eval',eval(formula))
这里罗列下我出现的问题
1 #如果formula传过去的时候是单独一个负数,如x,而我是用+—号进行分割的,分割完会出现第一个元素列表是空的情况,是空的情况如a 2 #这时候必须把第一个元素变成float格式的,否则无法就行后边的运算,但是常规方法将0赋值不行,必须先删除,在插入。 3 x='-1388420.3809523813' 4 a=['', '1388420.3809523813'] 5 b=['-'] 6 if a[0]=='': 7 a.remove('') 8 a.insert(0,'0') 9 print(a) 10 res=None 11 for index,i in enumerate(a): 12 if res: 13 if b[index-1]=='-': #这里要想清楚,因为这里至少是第二次,第二次-1,那么就是元素列表index的第一次 14 res -= float(i) 15 else: 16 res += float(i) 17 else: 18 res=float(i) 19 print('\033[31;1m[结果^^^%s]\033[0m' %res,'完成加减法运算后的结果')
1 #去括号这里出现了一个问题,前边教程用elif ('*' or '/') in item: 代替elif '*' in item or '/' in item: 2 #我实际测试时发生了问题,无法正确匹配'/',但是第一次的时候开业匹配,后边去除掉所有括号后竟然不能匹配了,还不报错 3 #所有该用elif '*' in item or '/' in item: 方法,后正常了,坑! 4 def delet_fuhao_fengmu(formula): 5 new_list=[] 6 print(formula,'测试16/10') 7 for index,item in enumerate(formula): 8 9 if item.strip().endswith('*')or item.strip().endswith('/'): 10 new_list.append('%s-%s'%(formula[index],formula[index+1])) 11 elif '*' in item or '/' in item: 12 #elif ('*' or '/') in item: 13 14 new_list.append(item) 15 print(new_list) 16 print(new_list,'这里是拼接分母后的列表,保留了需要进行乘法运算的元素') 17 return new_list
1 #这里也有问题,声明了一个sub_res变量,但是下边直接有if sub_res:,这里的意思是假如他存在,就执行加减法,不存在就给他赋值item,用于后边的运算,这里不太通顺,但是能用。
但是这里if的值应该是个布尔值,现在这么用不通顺。我选择得过且过了。 2 sub_res =None 3 for index,i in enumerate(sub_yuansu_list): 4 if sub_res: 5 if sub_yunsuanfu_list[index-1]=='*': 6 sub_res *= float(i) 7 else: 8 sub_res /= float(i) 9 else: 10 sub_res=float(i) 11 print('\033[31;1m[%s]=\033[0m'%item,sub_res,'这是完成乘法运算的结果')
一些测试代码
1 import re 2 # a='qiangql abc ccccabcabc' 3 # 4 # b=re.search('abc{2}',a) 5 # c=re.search('(abc){2}',a) 6 # print(b,c) 7 # d=re.search('\|','331|') 8 # print(d) 9 # 10 # w=re.sub('\s','',a) 11 # print(w) 12 #如果formula传过去的时候是单独一个负数,如x,而我是用+—号进行分割的,分割完会出现第一个元素列表是空的情况,是空的情况如a 13 #这时候必须把第一个元素变成float格式的,否则无法就行后边的运算,但是常规方法将0赋值不行必须先删除,在插入。 14 x='-1388420.3809523813' 15 a=['', '1388420.3809523813'] 16 b=['-'] 17 if a[0]=='': 18 a.remove('') 19 a.insert(0,'0') 20 print(a) 21 res=None 22 for index,i in enumerate(a): 23 if res: 24 if b[index-1]=='-': #这里要想清楚,因为这里至少是第二次,第二次-1,那么就是元素列表index的第一次 25 res -= float(i) 26 else: 27 res += float(i) 28 else: 29 res=float(i) 30 print('\033[31;1m[结果^^^%s]\033[0m' %res,'完成加减法运算后的结果') 31 32 # a='1-2*1388450.3809523813-12.5/10.6' 33 # a_yuansu=re.split('[+-]',a) 34 # a_yunsaunfu=re.findall('[*/]',a) 35 # print(a_yuansu,a_yunsaunfu) 36 # res=None 37 # for index,i in enumerate(a_yuansu): 38 # if res: 39 # if a_yunsaunfu[index-1]=='*': 40 # res *= res 41 # else: 42 # res /= res 43 # else: 44 # res=float(i) 45 # print(i,res) 46 #去括号这里出现了一个问题,前边教程用elif ('*' or '/') in item: 代替elif '*' in item or '/' in item: 47 #我实际测试时发生了问题,无法正确匹配'/',但是第一次的时候开业匹配,后边去除掉所有括号后竟然不能匹配了,还不报错 48 #所有该用elif '*' in item or '/' in item: 方法,后正常了,坑! 49 def delet_fuhao_fengmu(formula): 50 new_list=[] 51 print(formula,'测试16/10') 52 for index,item in enumerate(formula): 53 54 if item.strip().endswith('*')or item.strip().endswith('/'): 55 new_list.append('%s-%s'%(formula[index],formula[index+1])) 56 elif '*' in item or '/' in item: 57 #elif ('*' or '/') in item: 58 59 new_list.append(item) 60 print(new_list) 61 print(new_list,'这里是拼接分母后的列表,保留了需要进行乘法运算的元素') 62 return new_list
运算结果
1 C:\Users\qiangql\AppData\Local\Programs\Python\Python36-32\python.exe C:/Users/qiangql/PycharmProjects/untitled1/计算器3.py 2 (9-2*5/-3+7/3*99/4*2998+10*568/14) 正则出最里边的括号 3 去括号后 9-2*5/-3+7/3*99/4*2998+10*568/14 4 运算 9-2*5/-3+7/3*99/4*2998+10*568/14 5 ['9', '2*5/', '3', '7/3*99/4*2998', '10*568/14'] 乘法接口还没进入del符号 6 ['9', '2*5/', '3', '7/3*99/4*2998', '10*568/14'] 测试16/10 7 ['2*5/-3', '7/3*99/4*2998'] 8 ['2*5/-3', '7/3*99/4*2998', '10*568/14'] 9 ['2*5/-3', '7/3*99/4*2998', '10*568/14'] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 10 乘除里打印两个列表 ['2', '5', '-3'] ['*', '/'] 11 [2*5/-3]= -3.3333333333333335 这是完成乘法运算的结果 12 乘除里打印两个列表 ['7', '3', '99', '4', '2998'] ['/', '*', '/', '*'] 13 [7/3*99/4*2998]= 173134.50000000003 这是完成乘法运算的结果 14 乘除里打印两个列表 ['10', '568', '14'] ['*', '/'] 15 [10*568/14]= 405.7142857142857 这是完成乘法运算的结果 16 [9--3.3333333333333335+173134.50000000003+405.7142857142857]结果 这是在乘法里把结果替换为最准值 17 9--3.3333333333333335+173134.50000000003+405.7142857142857 未进行加减号替换运算符的formula 18 9+3.3333333333333335+173134.50000000003+405.7142857142857 这里把加减号进行替换后的formula 19 元素列表与运算符列表 ['9', '3.3333333333333335', '173134.50000000003', '405.7142857142857'] ['+', '+', '+'] 20 !!!!!!!!!!!!!!!!!!!!!!!!!!! 21 [结果^^^173552.54761904766] 完成加减法运算后的结果 22 173552.54761904766 完成一次运算后的值 23 1-2*(60-30+ (-40.0/5*173552.54761904766))-(-4*3)/(16-3*2) 完成替换后的值 24 (-40.0/5*173552.54761904766) 正则出最里边的括号 25 去括号后 -40.0/5*173552.54761904766 26 运算 -40.0/5*173552.54761904766 27 ['', '40.0/5*173552.54761904766'] 乘法接口还没进入del符号 28 ['', '40.0/5*173552.54761904766'] 测试16/10 29 ['40.0/5*173552.54761904766'] 30 ['40.0/5*173552.54761904766'] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 31 乘除里打印两个列表 ['40.0', '5', '173552.54761904766'] ['/', '*'] 32 [40.0/5*173552.54761904766]= 1388420.3809523813 这是完成乘法运算的结果 33 [-1388420.3809523813]结果 这是在乘法里把结果替换为最准值 34 -1388420.3809523813 未进行加减号替换运算符的formula 35 -1388420.3809523813 这里把加减号进行替换后的formula 36 元素列表与运算符列表 ['', '1388420.3809523813'] ['-'] 37 !!!!!!!!!!!!!!!!!!!!!!!!!!! 38 ['0', '1388420.3809523813'] 39 [结果^^^1388420.3809523813] 完成加减法运算后的结果 40 1388420.3809523813 完成一次运算后的值 41 1-2*(60-30+ 1388420.3809523813)-(-4*3)/(16-3*2) 完成替换后的值 42 (60-30+ 1388420.3809523813) 正则出最里边的括号 43 去括号后 60-30+ 1388420.3809523813 44 运算 60-30+ 1388420.3809523813 45 ['60', '30', ' 1388420.3809523813'] 乘法接口还没进入del符号 46 ['60', '30', ' 1388420.3809523813'] 测试16/10 47 [] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 48 [60-30+ 1388420.3809523813]结果 这是在乘法里把结果替换为最准值 49 60-30+ 1388420.3809523813 未进行加减号替换运算符的formula 50 60-30+ 1388420.3809523813 这里把加减号进行替换后的formula 51 元素列表与运算符列表 ['60', '30', ' 1388420.3809523813'] ['-', '+'] 52 !!!!!!!!!!!!!!!!!!!!!!!!!!! 53 [结果^^^1388450.3809523813] 完成加减法运算后的结果 54 1388450.3809523813 完成一次运算后的值 55 1-2*1388450.3809523813-(-4*3)/(16-3*2) 完成替换后的值 56 (-4*3) 正则出最里边的括号 57 去括号后 -4*3 58 运算 -4*3 59 ['', '4*3'] 乘法接口还没进入del符号 60 ['', '4*3'] 测试16/10 61 ['4*3'] 62 ['4*3'] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 63 乘除里打印两个列表 ['4', '3'] ['*'] 64 [4*3]= 12.0 这是完成乘法运算的结果 65 [-12.0]结果 这是在乘法里把结果替换为最准值 66 -12.0 未进行加减号替换运算符的formula 67 -12.0 这里把加减号进行替换后的formula 68 元素列表与运算符列表 ['', '12.0'] ['-'] 69 !!!!!!!!!!!!!!!!!!!!!!!!!!! 70 ['0', '12.0'] 71 [结果^^^12.0] 完成加减法运算后的结果 72 12.0 完成一次运算后的值 73 1-2*1388450.3809523813-12.0/(16-3*2) 完成替换后的值 74 (16-3*2) 正则出最里边的括号 75 去括号后 16-3*2 76 运算 16-3*2 77 ['16', '3*2'] 乘法接口还没进入del符号 78 ['16', '3*2'] 测试16/10 79 ['3*2'] 80 ['3*2'] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 81 乘除里打印两个列表 ['3', '2'] ['*'] 82 [3*2]= 6.0 这是完成乘法运算的结果 83 [16-6.0]结果 这是在乘法里把结果替换为最准值 84 16-6.0 未进行加减号替换运算符的formula 85 16-6.0 这里把加减号进行替换后的formula 86 元素列表与运算符列表 ['16', '6.0'] ['-'] 87 !!!!!!!!!!!!!!!!!!!!!!!!!!! 88 [结果^^^10.0] 完成加减法运算后的结果 89 10.0 完成一次运算后的值 90 1-2*1388450.3809523813-12.0/10.0 完成替换后的值 91 ----没拓号了...--- 92 运算 1-2*1388450.3809523813-12.0/10.0 93 ['1', '2*1388450.3809523813', '12.0/10.0'] 乘法接口还没进入del符号 94 ['1', '2*1388450.3809523813', '12.0/10.0'] 测试16/10 95 ['2*1388450.3809523813'] 96 ['2*1388450.3809523813', '12.0/10.0'] 97 ['2*1388450.3809523813', '12.0/10.0'] 这里是拼接分母后的列表,保留了需要进行乘法运算的元素 98 乘除里打印两个列表 ['2', '1388450.3809523813'] ['*'] 99 [2*1388450.3809523813]= 2776900.7619047626 这是完成乘法运算的结果 100 乘除里打印两个列表 ['12.0', '10.0'] ['/'] 101 [12.0/10.0]= 1.2 这是完成乘法运算的结果 102 [1-2776900.7619047626-1.2]结果 这是在乘法里把结果替换为最准值 103 1-2776900.7619047626-1.2 未进行加减号替换运算符的formula 104 1-2776900.7619047626-1.2 这里把加减号进行替换后的formula 105 元素列表与运算符列表 ['1', '2776900.7619047626', '1.2'] ['-', '-'] 106 !!!!!!!!!!!!!!!!!!!!!!!!!!! 107 [结果^^^-2776900.961904763] 完成加减法运算后的结果 108 109 110 最终结果: -2776900.961904763 111 eval 2776782.961904763 112 113 Process finished with exit code 0