通过正则表达式实现计算器功能

 

  1 #_*_encoding:utf-8_*_
  2 import re
  3 from functools import reduce
  4 #正则表达式练习题,将一个字符串中的数学表达式解析出来并计算出结果
  5 #1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )
  6 
  7 source = "1 - 2 * ( (6.0-30-1-3-4 +(--+40/5+2*5) * (9-2*5/3 +++++ 7 /3*99/4*2998 +10 * 568/14 )) -+ (+-4*3)/ (16-3*2) )"
  8 
  9 #判断字符串中是否有非法数学字符
 10 def match_validate(exp_string):
 11     re_pattern = "[^0-9\+\-\*\/\%\(\)\.%]+"    #将非0-9,不是+-*/().%的字符匹配出来
 12     res = re.findall(re_pattern,exp_string)
 13     if res : print(res)
 14     return res
 15 
 16 #判断是否有/*,*/,/%,等非+-,++,--,**的情况
 17 def operator_validate(exp_string):
 18     re_pattern = "[\*,/,\%]+[/,\%,\*]+"  # 将非0-9,不是+-*/().%的字符匹配出来
 19     res = re.findall(re_pattern, exp_string)
 20     if res: print(res)
 21     return res
 22 
 23 #将++,--,+-,-+等运算符号进行合并处理
 24 def combine_operator(exp_string):
 25 
 26     while(re.findall("\+[^0-9()]",exp_string) or re.findall("-[^0-9()]",exp_string)):
 27         exp_string = exp_string.replace('++','+')
 28         exp_string = exp_string.replace('+-', '-')
 29         exp_string = exp_string.replace('-+', '-')
 30         exp_string = exp_string.replace('--', '+')
 31 
 32     return exp_string
 33 
 34 #将表达式中的+-运算取出来进行计算,并将结果替换到原字符串中
 35 def cal_plus_minus(exp_string):
 36     re_pattern = "[+-]?[\d.]+[\+\-][\d.]+"
 37     while re.findall(re_pattern, exp_string):
 38 
 39         expression = re.search(re_pattern, exp_string).group()
 40 
 41         if expression.count("+"):
 42             #当存在两个带+的数据相加时,使用+分隔会产生三个数,需要处理分隔为''的情况
 43             cal_rst = reduce(lambda x, y:float(x) + float(y), filter( lambda x: x!='',expression.split("+")))
 44 
 45             exp_string = exp_string.replace(expression, str(cal_rst))
 46 
 47             exp_string = combine_operator(exp_string)
 48 
 49         else:
 50 
 51             cal_rst = 0
 52 
 53             if(expression.startswith('-')):  #当两个负数相加的情况,则直接计算相加的结果再取反
 54                 cal_rst = reduce(lambda x, y: float(x) + float(y), filter(lambda x: x != '', expression.split("-")))
 55                 cal_rst = -cal_rst
 56             else:
 57                 cal_rst = reduce(lambda x, y: float(x) - float(y),  expression.split("-"))
 58 
 59             exp_string = exp_string.replace(expression, str(cal_rst))
 60 
 61             exp_string = combine_operator(exp_string)
 62 
 63     return exp_string
 64 
 65 #将表达式中的*/运算取出来进行计算,并将结果替换到原字符串中
 66 def cal_multiple_divide(exp_string):
 67     re_pattern = "[\d.]+[\*\/][+-]?[\d.]+"
 68     while re.findall(re_pattern, exp_string):
 69 
 70         expression = re.search(re_pattern,exp_string).group()   #获取表达式
 71 
 72         if expression.count("*"):                               #计算乘法结果,并将原来的表达式进行替换
 73             cal_rst = reduce(lambda x,y:float(x)*float(y),expression.split("*"))
 74 
 75             exp_string = exp_string.replace(expression, str(cal_rst))
 76 
 77             exp_string = combine_operator(exp_string)
 78         if expression.count("/"):                               #计算除法结果,并将原来的表达式进行替换
 79             cal_rst = reduce(lambda x, y: float(x) /  float(y), expression.split("/"))
 80 
 81             exp_string = exp_string.replace(expression, str(cal_rst))
 82 
 83             exp_string = combine_operator(exp_string)
 84 
 85     return exp_string
 86 
 87 #将字符串中的所有空格去掉
 88 new_string = source.replace(' ','')
 89 
 90 if match_validate(new_string):
 91     print("exists invalid character!!")             #如果存在非数学字符,则提示
 92 elif operator_validate(new_string):
 93     print("invalid operator character!!")           #如果存在无法计算的操作,则提示
 94 else:
 95     new_string = combine_operator(new_string)           #处理++,--,+-,--情况
 96 
 97     while new_string.count("(")>0:     #判断表达式中是否还有()运算符
 98         # 找到最里层的括号开始计算
 99         re_pattern = "\([^()]*\)"
100         # 找到最里层的括号表达式,通过search+group方式,从前面挨个取出,findall找到的是所有的,并返回列表,这里不好用
101         exp_string  = re.search(re_pattern, new_string).group()
102 
103         # 计算表达式中的所有*/运算
104         res_string = cal_multiple_divide(exp_string)
105         #将*/运算计算的结果替换表达式中计算前的表达式
106         new_string = new_string.replace(exp_string, res_string)
107         #将出现的+-符号重叠的情况进行处理
108         exp_string = combine_operator(exp_string)
109 
110         #将最底层括号内*/计算完的结果作为+-计算的表达式
111         exp_string =res_string
112         # 计算+-  运算
113         res_string = cal_plus_minus(exp_string)
114         #将+-运算的结果替换原字符串中的表达式,同时将()替换掉
115         new_string = new_string.replace(exp_string, res_string[1:-1])
116         # 将出现的+-符号重叠的情况进行处理
117         new_string = combine_operator(new_string)
118 
119     else:
120         #没有括号的情况下先计算*/运算
121         res_string = cal_multiple_divide(new_string)  # 计算*/
122         new_string = new_string.replace(new_string, res_string)
123         new_string = combine_operator(new_string)
124 
125         # 再计算+-运算
126         res_string = cal_plus_minus(new_string)
127         # 将+-运算的结果替换原字符串中的表达式
128         new_string = new_string.replace(new_string, res_string)
129         # 处理+-,++,--,-+等情况
130         new_string = combine_operator(new_string)
131 
132         print(source,"=",new_string)

 

posted on 2018-03-29 14:25  星际无垠  阅读(142)  评论(0)    收藏  举报