python 正则的使用 —— 编写一个简易的计算器
在 Alex 的博客上看到的对正则这一章节作业是编写一个计算器,要求能计算出下面的算式。
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 . 程序不完善之处,这个程序只支持加减乘除四则运算,功能还不够完善;由于python 自身的原因,在计算浮点数上,有时会出现不准确的情况,这个还需要在完善一下;为了方便处理,我是将所有的数字都转化为浮点数处理,故一些整数间的运算得到的结果也会是一个浮点数,还需要继续完善。
附上代码:
``` import re x = input('请输入你要计算的计算式:') # 用户输入 # 判断用户输入的是否有字母,括号个数是否正确,同时处理字符串中的空格 if re.findall('[a-zA-Z]',x): print('输入错误,算式中出现字母!') exit() if '(' in x or ')' in x: if x.count('(') != x.count(')'): print('输入错误,括号个数不正确!') exit() if ' ' in x: x = x.replace(' ','') # 定义一个处理乘法和除法的函数,在只有加减乘除的运算中,除法若是最优先运算的话,不会出错。 # 经过这个函数处理后,计算式中的 乘除法就处理完了,只剩下加减法了 def multiplication_division(calculate): # 在计算完括号里面的计算式时,如果得到一个负数,那么替换后会出现 '*-' '/-' '+-' '--' 这么几种情况,故函数先判断处理这种情况。 while '*-' in calculate: if re.search('-[0-9.]+\*-',calculate): replace1 = re.search('-[0-9.]+\*-',calculate).group() replace = replace1.replace('*-','*') replace = replace.replace('-','+') calculate = calculate.replace(replace1,replace) elif re.search('\+[0-9.]+\*-',calculate): replace1 = re.search('\+[0-9.]+\*-', calculate).group() replace = replace1.replace('*-', '*') replace = replace.replace('+', '-') calculate = calculate.replace(replace1, replace) while '/-' in calculate: if re.search('-[0-9.]+/-',calculate): replace1 = re.search('-[0-9.]+/-',calculate).group() replace = replace1.replace('/-','/') replace = replace.replace('-','+') calculate = calculate.replace(replace1,replace) elif re.search('\+[0-9.]+/-',calculate): replace1 = re.search('\+[0-9.]+/-', calculate).group() replace = replace1.replace('/-', '/') replace = replace.replace('+', '-') calculate = calculate.replace(replace1, replace) while '/' in calculate: if re.findall('^-[0-9.]+/[0-9.]+',calculate): division = re.findall('-[0-9.]+/[0-9.]+',calculate)[0] result = re.findall('(-[0-9.]+)/([0-9.]+)',division)[0] result = float(result[0])/float(result[1]) calculate = calculate.replace(division,str(result)) else: division = re.findall('[0-9.]+/[0-9.]+',calculate)[0] result = re.findall('([0-9.]+)/([0-9.]+)',division)[0] result = float(result[0])/float(result[1]) calculate = calculate.replace(division,str(result)) while '*' in calculate: if re.findall('^-[0-9.]+\*[0-9.]+', calculate): multiplication = re.findall('-[0-9.]+\*[0-9.]+',calculate)[0] result = re.findall('(-[0-9.]+)\*([0-9.]+)',multiplication)[0] result = float(result[0])*float(result[1]) calculate = calculate.replace(multiplication,str(result)) else: multiplication = re.findall('[0-9.]+\*[0-9.]+', calculate)[0] result = re.findall('([0-9.]+)\*([0-9.]+)', multiplication)[0] result = float(result[0]) * float(result[1]) calculate = calculate.replace(multiplication, str(result)) return calculate # 定义一个处理只有加减法的函数 def addition_subtraction(calculate): if '+-' in calculate: calculate = calculate.replace('+-','-') elif '--' in calculate: calculate = calculate.replace('--','+') list_number = [] list_number_ = re.findall('[+-]?[0-9.]+',calculate) for i in list_number_: list_number.append(float(i)) return sum(list_number) # 找到最里面的括号,并传给前面的乘除法运算和加减法运算,得到最终的结果 def final(x): while '(' in x: process = re.findall('\(([^()]+)\)',x) for calculate in process: y = multiplication_division(calculate) y = addition_subtraction(y) x = x.replace('('+calculate+')',str(y)) x = multiplication_division(x) return addition_subtraction(x) print(final(x)) ```