Python之实现一个简易计算器 用re
功能分析
用户输入一个类似这样 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) 这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号,然后自己动手写代码解析其中的表达式,实现加减乘除,最后得出的结果与真实的计算机所算的结果必须一致。
程序实现流程分析
从最简单的开始。
1、按运算符的优先级别,先编写一个程序实现对字符串的乘除处理
2、再编写一个程序实现对字符串的加减处理
3、编写一个程序实现对括号内容匹配处理
4、编写对原始字符串数据的处理,甄别。是否输入错误等。。。。
实现:
1、先实现乘除功能:
# -*- coding:utf-8 -*- import re ''' Created on 2018年7月10日 @author: Administrator ''' #第一步,实现一个公式的乘除 #9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 假设没有空格在里面 sub_s='9-10.0/3 + 7/3*99/4*2998 +10*568/14 ' print(sub_s) #先计算乘除 def chengchu(gongshi): new_s_s=gongshi if '*' in new_s_s or '/' in new_s_s:#先计算乘除 sub_sub_s=re.search('(\d*\.?\d*)([*/])(\d*\.?\d*)',new_s_s) if sub_sub_s==None: pass else: # print(sub_sub_s) # print(sub_sub_s.span()) # print(sub_sub_s.group()) if sub_sub_s.group(2)=='*': sss=str(float(sub_sub_s.group(1))*float(sub_sub_s.group(3))) # print(sss) elif sub_sub_s.group(2)=='/': sss = str(float(sub_sub_s.group(1)) / float(sub_sub_s.group(3))) # print(sss) else: print('没有需要运算的乘除法。') # s_new=s[0:18]+'-8'+s[25:] # gongshi[0:sub_sub_s.span()[0]] + sss + gongshi[sub_sub_s.span()[1]:] new_s_s=gongshi[0:sub_sub_s.span()[0]]+sss+gongshi[sub_sub_s.span()[1]:] # print(new_s_s) return chengchu(new_s_s) else: return new_s_s # if '+' in gongshi or '-' in gongshi: # 再计算加减 #再计算加减 def jiajian(): pass print(chengchu(sub_s))
运行结果:
"D:\Program Files (x86)\python36\python.exe" F:/python从入门到放弃/7.5/计算器.py 9-10.0/3 + 7/3*99/4*2998 +10*568/14 9-3.3333333333333335 + 173134.50000000003 +405.7142857142857 Process finished with exit code 0
2、实现加减功能:
1 #再计算加减 sub_s_s=9-3.3333333333333335 + 173134.50000000003 +405.7142857142857 2 sub_s_s='9-3.3333333333333335+173134.50000000003+405.7142857142857' #假设没有空格 3 print(sub_s_s) 4 def jiajian(gongshi_jiajian): 5 new_s_s = gongshi_jiajian 6 if '+' in new_s_s or '-' in new_s_s:#计算加减 7 sub_sub_s=re.search('(\d*\.?\d*)([+-])(\d*\.?\d*)',new_s_s) 8 if sub_sub_s==None: 9 pass 10 else: 11 if sub_sub_s.group(2) == '+': 12 sss=str(float(sub_sub_s.group(1))+float(sub_sub_s.group(3))) 13 # print(sss) 14 elif sub_sub_s.group(2)=='-': 15 sss = str(float(sub_sub_s.group(1)) - float(sub_sub_s.group(3))) 16 # print(sss) 17 else: 18 print('没有需要运算的加减法。') 19 new_s_s = sss + gongshi_jiajian[sub_sub_s.span()[1]:] 20 # print(new_s_s) 21 return jiajian(new_s_s) 22 else: 23 return new_s_s 24 25 print(jiajian(sub_s_s))
运行结果:
"D:\Program Files (x86)\python36\python.exe" F:/python从入门到放弃/7.5/计算器.py 9-3.3333333333333335+173134.50000000003+405.7142857142857 173545.88095238098 Process finished with exit code 0
3、实现匹配出最里层的括号内容
1 # -*- coding:utf-8 -*- 2 import re 3 ''' 4 Created on 2018年7月9日 5 6 @author: Administrator 7 ''' 8 #用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 9 # 这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号 10 s='1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )' 11 s1='1 - 2 * ( (60-30* (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )' 12 def kuohao(gongshi_kuohao):#输入带括号的公式 13 str_kuohao=gongshi_kuohao 14 if '(' in str_kuohao and ')' in str_kuohao: 15 guize_kuohao = re.compile('(\()([^()]*)(\))') # 匹配出最里层的括号的规则 16 print(guize_kuohao.search(str_kuohao)) 17 print(guize_kuohao.search(str_kuohao).group()) 18 print(guize_kuohao.search(str_kuohao).group(1)) 19 print(guize_kuohao.search(str_kuohao).group(2))#取到最里层括号里面的字符串 20 print(guize_kuohao.search(str_kuohao).group(3)) 21 22 print(kuohao(s)) 23 print(kuohao(s1))
运行结果:
"D:\Program Files (x86)\python36\python.exe" F:/python从入门到放弃/7.5/计算器.py <_sre.SRE_Match object; span=(18, 25), match='(-40/5)'> (-40/5) ( -40/5 ) None <_sre.SRE_Match object; span=(18, 58), match='(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )'> (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ) ( 9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ) None Process finished with exit code 0
4、实现原始字符串错误检测,处理功能
1 # -*- coding:utf-8 -*- 2 import re 3 ''' 4 Created on 2018年7月9日 5 6 @author: Administrator 7 ''' 8 #用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 9 # 这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号 10 s='1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' 11 def qingxi(gongshi_qingxi):##对原始公式进行清洗、 12 str_qingxi_kongge=re.sub('\s','',gongshi_qingxi)#去掉所有空格 13 # print(str_qingxi_kongge) 14 #统计括号 15 str_qingxi_kuohao=re.findall('[\(\)]',str_qingxi_kongge) 16 # print(str_qingxi_kuohao) 17 if str_qingxi_kuohao.count('(')==str_qingxi_kuohao.count(')'):#左括号和右括号相等 18 for i in range(1,int(len(str_qingxi_kuohao))):#判断左侧的左括号,要一直大于等于左侧的右括号 19 # print(i) 20 if str_qingxi_kuohao[0:i].count('(') >= str_qingxi_kuohao[0:i].count(')'): 21 continue 22 else: 23 print('公式中括号出现错误,请检查第 %d 括号问题'%i) 24 else: 25 print('公式中括号出现错误,括号不是成对出现。') 26 # if re.search('\([^\d]\)',str_qingxi_kongge): 27 # print('公式中括号出现错误,出现空括号') 28 29 return str_qingxi_kongge 30 31 print(qingxi(s))
结果:
"D:\Program Files (x86)\python36\python.exe" F:/python从入门到放弃/7.5/计算器.py 1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) Process finished with exit code 0
最终结果:(对于之前写的代码,存在逻辑上漏洞,也在下面代码中改善)
1 # -*- coding:utf-8 -*- 2 import re 3 4 ###############################################清洗,格式化字符串######################################################################### 5 def qingxi(string):##对原始公式进行清洗、 6 flag=True 7 string=string.replace(' ','')#去掉所有空格 8 string = string.replace('+-', '-') 9 string = string.replace('--', '+') 10 string = string.replace('++', '+') 11 string = string.replace('-+', '-') 12 string = string.replace('*+', '*')#假设,只有加减乘除运算。输入时可能出现,但是运算中不可能遇到这种情况 13 string = string.replace('/+', '/') #假设,只有加减乘除运算。输入时可能出现,但是运算中不可能遇到这种情况 14 #防止出现 类似 2*-3==(-1)*2*3 15 s_str=re.search('(\d+\.?\d*\*)(-)', string) 16 if s_str : 17 s_str=s_str.group(1)#拿到-前面的数字 2* 18 string = re.sub('\d+\.?\d*\*-', '-'+s_str, string) # 防止出现 类似 2*-3==-2*3 19 s_str_sub = re.search('(\d+\.?\d*/)(-)', string) 20 if s_str_sub: 21 s_str = s_str_sub.group(1) # 拿到-前面的数字 2* 22 string = re.sub('\d+\.?\d*/-', '-' + s_str, string) # 防止出现 类似 2/-3==-2/3 23 24 # 遇到+- 或是-+ 统统换成- 运算符 25 str_qingxi=re.findall('[\(\)]',string) 26 if re.findall('[a-z]+',string.lower()): 27 print('存在非法字符',re.findall('[a-z]+',string.lower())) 28 flag=False 29 elif str_qingxi.count('(')==str_qingxi.count(')'):#左括号和右括号相等 ()必须成对出现 30 for i in range(1,int(len(str_qingxi))):#判断左侧的左括号,要一直大于等于左侧的右括号,防止出现类似 ))(( 的情况 31 if str_qingxi[0:i].count('(') >= str_qingxi[0:i].count(')'): 32 continue 33 else: 34 print('公式中括号出现错误,请检查第 %d 处括号问题'%i) 35 flag=False 36 else: 37 print('公式中括号出现错误,存在括号没有闭合。') 38 if flag: 39 return string 40 ###############################################乘除计算######################################################################### 41 def chengchu(string): 42 43 44 if '*' in string or '/' in string:#先计算乘除 45 s_string = re.search('(\d+\.?\d*)([*/])(\d+\.?\d*)', string) 46 s_s_string=s_string.group()# 47 # s_string = re.search('(\d+\.?\d*)([*/])(\d+\.?\d*)', string) 48 # s_s_string = s_string.group() 49 # if s_string: 50 51 if s_string.group(2)=='*': 52 sss=str(float(s_string.group(1))*float(s_string.group(3))) 53 # print(sss) 54 new_string = string.replace(s_s_string, sss) 55 return chengchu(new_string) 56 elif s_string.group(2)=='/': 57 sss = str(float(s_string.group(1)) / float(s_string.group(3))) 58 # print(sss) 59 new_string = string.replace(s_s_string, sss) 60 return chengchu(new_string) #递归。。。 61 else: 62 # print('没有需要运算的乘除法。') 63 return string 64 65 ###############################################加减计算######################################################################### 66 def jiajian(string): 67 s_string = re.search('(\d+\.?\d*)([+-])(\d+\.?\d*)', string) 68 if s_string:#条件成立,表示匹配到加法,或是加法公式。如果匹配'-5',则条件不成立,没有返回值 69 s_s_string=s_string.group() 70 if s_string.group(2) == '+': 71 sss=str(float(s_string.group(1))+float(s_string.group(3))) 72 new_string=string.replace(s_s_string,sss) 73 return jiajian(new_string) 74 elif s_string.group(2)=='-': 75 sss =str(float(s_string.group(1)) - float(s_string.group(3))) 76 new_string=string.replace(s_s_string,sss) 77 return jiajian(new_string) 78 else: 79 # print('没有需要运算的加减法。') 80 return string 81 ###############################################组合计算######################################################################### 82 def jisuanqi(string):#计算器函数 83 84 while re.search('\(',string):#有括号 85 string = qingxi(string)#每对最里层的括号运算一次,清洗一下,防止出现'--5',‘+-8’ 等情况 86 strs=re.search('\([^()]+\)',string).group()#检测最里层的括号 87 # strs_s_s=strs.group() 88 strs_s=chengchu(strs)# 89 strs_s=qingxi(strs_s) 90 strs_s=jiajian(strs_s).strip('()')# 91 string=string.replace(strs,strs_s) 92 93 else:#无括号 94 string = qingxi(string)#每对最里层的括号运算一次,清洗一下,防止出现'--5',‘+-8’ 等情况 95 strs = chengchu(string) 96 strs=qingxi(strs) 97 strs = jiajian(strs) 98 return strs# 99 100 101 102 sour='1 + 2 * ((60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) +- (-4*3)/ (16-3*2))' 103 s1=jisuanqi(sour) 104 print(s1)
运行结果:
"D:\Program Files (x86)\python36\python.exe" F:/python从入门到放弃/计算器3.py -2776675.4952380955 Process finished with exit code 0