python 计算器 -----递归 正则练习
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import re,time def compte_add_sub(inp): arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) arg = re.findall("[\+\-]|\d+\.?\d*",arg) # if arg[0] == "-": arg[0]=arg[0]+arg[1] del arg[1] add_sum = float(arg[0]) for i in range(1,len(arg),2): if arg[i] == "+": add_sum +=float(arg[i+1]) elif arg[i] == "-": add_sum -= float(arg[i+1]) return add_sum #处理乘除 def compute_mul_div(arg): arg = arg[0] end =len(arg) ###########计算平方########## arg = re.sub("(//)","/",arg) #print(arg) while True: x = re.search("\d+\.*\d*(\*\*)\d+\.*\d*",arg) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) arg = arg.replace(expre,str(ret),1) print(arg) else: #print("exit") break ###########计算平方########## li = re.findall(r"[*/]",arg) num = len(li) for i in range(num): new = arg.split(li[i],1) la=re.findall("[\+\-\/]?(\d+\.?\d*)",new[0])[-1] sta = re.findall("([\+\-\/]?\d+\.?\d*)",new[1])[0] if li[i] == "*": new_che = float(la) * float(sta) else: new_che = float(la) / float(sta) arg = new[0][0:-len(la)] + str(new_che) +new[1][len(sta):] arg=[arg,] return compte_add_sub(arg) def comput(expression): inp = [expression,] n= compute_mul_div(inp) return n def excut(expression): kuohao=[] if expression.find("(") == -1: ret = comput(expression) return ret for i in range(len(expression)): if "(" == expression[i]: kuohao.append(i) elif ")" == expression[i]: ans_kuo = expression[kuohao[-1]+1:i] ret_num = comput(ans_kuo) expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] return excut(expression) def main(): a = '1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' default = '1-40/5*5+3-2*5/3' a = default if len(a) == 0 else re.sub("\s*", '', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\033[33;1m公式为:\033[0m",a) print("\033[35;1m结果为:\033[0m",ret) if __name__ == '__main__': start = time.clock() main() end = time.clock() print("read: %f s" % (end - start))
C:\Python35\python3.exe E:/py_test/s3_py/real_cal_liujianzuo.py 公式为: 1-2*((60-30+(1-40/5*5+3-2*5/3)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) 结果为: 13652214.56825397 read: 0.001188 s
version1
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import re def compte_add_sub(inp): # inp = ['-9-8.8++9--9',] arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 #去除++ +- -- -+ if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) new_m = re.search('[\-]*\d+\.*\d*[\-\+]+\d+\.*\d*',arg) # 匹配 -9.9 + 9.9 或者 -9.9 - 9.9 if not new_m: # print(arg) return arg # 递归处理,当匹配不到上面的表达式就将表达式结果返回 即处理加减后的结果 else: brefor,after = re.split('[\-]*\d+\.*\d*[\+\-]+\d+\.*\d*',arg,1) #以匹配到的表达式为分隔符 分割 new_m=new_m.group() #定义成列表 将匹配到的表达式 if new_m.find("+") != -1: #如果匹配的是+号 new_m=new_m.split("+") #以+号分割 # print(new_m) zhi = float(new_m[0]) + float(new_m[1]) #计算加号 else: #减号的话 if new_m.startswith("-"): #如果匹配到的表达式以减号开头 #对应的序列元素第一个是空 new_m=new_m.split("-") #以减号分割 zhi = -(float(new_m[1]) + float(new_m[2])) #提出减号 内部相加即可 # print(zhi) else: #如果不以减号开头则 直接按分割收的序列 new_m=new_m.split("-") # print(new_m) zhi = float(new_m[0]) - float(new_m[1]) #zhi = float('%0.6f'%zhi) #浮点数优化精度 #print(zhi) arg = brefor + str(zhi) +after #字符串类型进行拼接 # print(arg) inp = [arg,] #更改列表 # print(inp) return compte_add_sub(inp) #处理乘除 def compute_mul_div(arg): #arg = ['9-2*5/3+7/3*99/4*2998+10*568/14', 0] val = arg[0] #取出表达式 ###########计算平方########## val = re.sub("(//)","/",val) #print(arg) while True: x = re.search("\d+\.*\d*(\*\*)\d+\.*\d*",val) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) val = val.replace(expre,str(ret),1) print(val) else: #print("exit") break ###########计算平方########## mch = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val) # 由于递归,首先判断传入的表达式满足要求与否, 例子: 9.9 * 9.8 或者 9.9 /9.8 是否包含。 if not mch: return #退出函数 因为arg是列表与comput的inp列表指向的同一个内存地址,故不需要返回值 content = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val).group() #存在 例子: 9.9 * 9.8 或者 9.9 /9.8 的话取出 if len(content.split('*')) > 1: # 判断是否* 进行分割查看长度,有*的话则会大于1 没有就是/ n1, n2 = content.split('*') value = float(n1) * float(n2) else: n1, n2 = content.split('/') value = float(n1) / float(n2) #value = float('%0.7f'%value) #float 类型取7个精度 即小数点后7位,否则太长影响效率 before, after= re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val, 1) #以表达式进行分割,1是从左到右 匹配第一个合适的。 类似 字符串的split new_str = '%s%s%s' % (before, value, after) #拼接 # print(new_str) arg[0] = new_str #更新列表的值 return compute_mul_div(arg) #递归处理 def comput(expression): # expression = "9-2*5/3+7/3*99/4*2998+10*568/14" #将传入的四则做成列表 这样修改函数形参则该列表也变化,因此不用return也行 inp = [expression,] # 处理乘除 方法 compute_mul_div(inp) # 处理加减 return compte_add_sub(inp) def excut(expression): kuohao=[] # 左括号 索引加入列表 if expression.find("(") == -1: #如果匹配不到左括号就直接交给计算四则的函数 ret = comput(expression) return ret for i in range(len(expression)): if "(" == expression[i]: # 循环字符串,遇到左括号加入空列表 kuohao.append(i) elif ")" == expression[i]: # 一旦遇到右括号,就跟上面左括号列表的最后一个元素还有遇到的这个右括号进行切片 ans_kuo = expression[kuohao[-1]+1:i] ret_num = comput(ans_kuo) expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] print(expression) return excut(expression) # # \(([\+\-\*\/]*\d+\.*\d*){2,}\) 是找 这一类 : 括号开始 接+ - * / 然后是数字1个或多个 小数点 数字0个或多个 类似-77.77 至少匹配2次 然后 括号结尾 : (-77.9*-88+99/3) # if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expresiong): # final = comput(expresiong) #匹配不到了就交个这个计算四则的方法 # return final # jus = re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expresiong).group() #取得括号表达式 (1-40/5*5+3-2*5/3) # #print(jus) # befor, nothing, after = re.split('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expresiong, 1) #以单层括号表达式分割 (1-40/5*5+3-2*5/3) 比如, 作为分隔符 但是只显示/3 这部分,所以先在上面取到表达式 # #print(nothing) # jus = jus[1:len(jus) - 1] #去除 分割表达式的括号 :1-40/5*5+3-2*5/3 # #print('222', jus) # result = comput(jus) #交给四则运算的方法 # result = float(result) # #result = float('%0.7f'%result) # result=str(result) # #print(result) # new_expression = "%s%s%s" % (befor, result, after) #四则计算完后拼接 # # print(new_expression) # return excut(new_expression) #将新的表达式返回给函数 ,递归处理 def main(): # a = '1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' default = '1-2*(3+4)-6/3-6+7' a = input("\033[35;1m请输入表达式,只能包含小数点 四则运算符 小括号\n表达式:\033[0m") lx = re.sub("[\d+\.\+\-\*\/\s*\(\)]","",a) if len(lx) != 0: print("\033[31;1m表达式有其他特殊符号\033[0m") return main() if "(" in a: if a.count("(") != a.count(")"): print("\033[31;1m表达式括号个数不匹配\033[0m") return main() a = default if len(a) == 0 else re.sub("\s*", '', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\033[33;1m公式为:\033[0m",a) print("\033[35;1m结果为:\033[0m",ret) if __name__ == '__main__': main()
version2
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import re def compte_add_sub(inp): # inp = ['-9-8.8++9--9',] arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 #去除++ +- -- -+ if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) new_m = re.search('[\-]*\d+\.*\d*[\-\+]+\d+\.*\d*',arg) # 匹配 -9.9 + 9.9 或者 -9.9 - 9.9 if not new_m: #print(1766666,arg) return arg # 递归处理,当匹配不到上面的表达式就将表达式结果返回 即处理加减后的结果 else: brefor,after = re.split('[\-]*\d+\.*\d*[\+\-]+\d+\.*\d*',arg,1) #以匹配到的表达式为分隔符 分割 new_m=new_m.group() #定义成列表 将匹配到的表达式 if new_m.find("+") != -1: #如果匹配的是+号 new_m=new_m.split("+") #以+号分割 # print(new_m) zhi = float(new_m[0]) + float(new_m[1]) #计算加号 else: #减号的话 if new_m.startswith("-"): #如果匹配到的表达式以减号开头 #对应的序列元素第一个是空 new_m=new_m.split("-") #以减号分割 zhi = -(float(new_m[1]) + float(new_m[2])) #提出减号 内部相加即可 # print(zhi) else: #如果不以减号开头则 直接按分割收的序列 new_m=new_m.split("-") # print(new_m) zhi = float(new_m[0]) - float(new_m[1]) #zhi = float('%0.6f'%zhi) #浮点数优化精度 #print(zhi) arg = brefor + str(zhi) +after #字符串类型进行拼接 # print(arg) inp = [arg,] #更改列表 # print(inp) return compte_add_sub(inp) #处理乘除 def compute_mul_div(arg): arg = arg[0] #print(arg) end =len(arg) ###########计算平方########## arg = re.sub("(//)","/",arg) #print(arg) while True: x = re.search("\d+\.*\d*(\*\*)\d+\.*\d*",arg) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) arg = arg.replace(expre,str(ret),1) print(arg) else: #print("exit") break ###########计算平方########## # num = arg.count("*",0,end) +arg.count("/",0,end) li = re.findall(r"[*/]",arg) #匹配 * / 做到列表 #print(li) num = len(li) for i in range(num): #循环列表的下标 new = arg.split(li[i],1) #以乘除号为分隔符进行分割 la=re.findall("[\+\-\/]?(\d+\.?\d*)",new[0])[-1] #获取分隔符左侧字符串的最后一个数字,匹配浮点数 sta = re.findall("([\+\-\/]?\d+\.?\d*)",new[1])[0] #获取分隔符右侧字符串的第一一个数字,匹配浮点数 #print(la,sta) if li[i] == "*": #如果分隔符是* 计算乘 new_che = float(la) * float(sta) else: new_che = float(la) / float(sta) #print(new_che) # arg = re.sub(la+"*"+sta,new_che,new,1) arg = new[0][0:-len(la)] + str(new_che) +new[1][len(sta):] # 分割拼接 #print(arg) arg=[arg,] #print(3333333333,arg) return compte_add_sub(arg) def comput(expression): # expression = "9-2*5/3+7/3*99/4*2998+10*568/14" #将传入的四则做成列表 这样修改函数形参则该列表也变化,因此不用return也行 inp = [expression,] # 处理乘除 方法 n= compute_mul_div(inp) return n def excut(expression): kuohao=[] if expression.find("(") == -1: ret = comput(expression) return ret for i in range(len(expression)): if "(" == expression[i]: kuohao.append(i) elif ")" == expression[i]: ans_kuo = expression[kuohao[-1]+1:i] ret_num = comput(ans_kuo) expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] #print(expression) return excut(expression) def main(): # a = '1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' default = '1-2*(3+4)-6/3-6+7' a = input("\033[35;1m请输入表达式,只能包含小数点 四则运算符 小括号\n表达式:\033[0m") lx = re.sub("[\d+\+\.\-\*\/\s*\(\)]","",a) if len(lx) != 0: print("\033[31;1m表达式有其他特殊符号\033[0m") return main() if "(" in a: if a.count("(") != a.count(")"): print("\033[31;1m表达式括号个数不匹配\033[0m") return main() a = default if len(a) == 0 else re.sub("\s*", '', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\033[33;1m公式为:\033[0m",a) print("\033[35;1m结果为:\033[0m",ret) # "1-2*60-30+1-40/5*5+3-2*5/3*9-2*5/3+7/3*99/4*2998+10*568/14--4*3/16-3*2" if __name__ == '__main__': main()
version3
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import re,time def compte_add_sub(inp): arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) arg = re.findall("[\+\-]|\d+\.?\d*",arg) # if arg[0] == "-": arg[0]=arg[0]+arg[1] del arg[1] add_sum = float(arg[0]) for i in range(1,len(arg),2): if arg[i] == "+": add_sum +=float(arg[i+1]) elif arg[i] == "-": add_sum -= float(arg[i+1]) return add_sum def compute_mul_div(arg): arg = arg[0] end =len(arg) ###########计算平方########## arg = re.sub("(//)","/",arg) #print(arg) while True: x = re.search("\d+\.*\d*(\*\*)\d+\.*\d*",arg) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) arg = arg.replace(expre,str(ret),1) print(arg) else: #print("exit") break ###########计算平方########## li = re.findall(r"[*/]",arg) num = len(li) for i in range(num): new = arg.split(li[i],1) la=re.findall("[\+\-\/]?(\d+\.?\d*)",new[0])[-1] sta = re.findall("([\+\-\/]?\d+\.?\d*)",new[1])[0] if li[i] == "*": new_che = float(la) * float(sta) else: new_che = float(la) / float(sta) arg = new[0][0:-len(la)] + str(new_che) +new[1][len(sta):] arg=[arg,] return compte_add_sub(arg) def comput(expression): inp = [expression,] n= compute_mul_div(inp) return n def excut(expression): # kuohao=[] # if expression.find("(") == -1: # ret = comput(expression) # return ret # for i in range(len(expression)): # if "(" == expression[i]: # kuohao.append(i) # elif ")" == expression[i]: # ans_kuo = expression[kuohao[-1]+1:i] # ret_num = comput(ans_kuo) # expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] # return excut(expression) n = re.search("\(([^()]+)\)",expression) if not n: ret = comput(expression) return ret comp = n.group() # (1-40/5*5+3-2*5/3) print(comp) # sp = re.split("\(([^()]+)\)",expression,1) before,nothing,after = re.split("\(([^()]+)\)",expression,1) result = comput(comp[1:-1]) expression = "%s%s%s"%(before,result,after) return excut(expression) def main(): default = '1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))' default = re.sub("\s*", '', default) a = input("\033[35;1m请输入表达式,只能包含小数点 四则运算符 小括号\n表达式:\033[0m") lx = re.sub("[\d+\.\+\-\*\/\s*\(\)]","",a) if len(lx) != 0: print("\033[31;1m表达式有其他特殊符号\033[0m") return main() if "(" in a: if a.count("(") != a.count(")"): print("\033[31;1m表达式括号个数不匹配\033[0m") return main() a = default if len(a) == 0 else re.sub("\s*", '', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\033[33;1m公式为:\033[0m",a) print("\033[35;1m结果为:\033[0m",ret) if __name__ == '__main__': main()