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)