正则计算器版中版之最后一版!

作业要求是用正则编写一个计算器,可以计算长公司的计算器


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

 

 

posted @ 2018-04-25 14:57  人无远虑  阅读(311)  评论(0编辑  收藏  举报