Python编写简单计算器(正则表达式应用)
需求——开发一个简单的Python计算器
1.实现加减乘除以及括号优先级解析
2.用户输入3+5*((80-40+(-40/8)*(9-2*9/3-5/3*98/4*2998+10*568/14))-(-4*6)/(27-3*8))等类似公式后,必须自己解析出里面的各种符号(不得调用eval等偷懒),运算后得出结果,结果要正确。
总程序
1 import re 2 #一、对公式进行简单处理(去掉空格及公式化简) 3 def format_string(string): 4 string = string.replace(' ','') 5 string = string.replace('++','+') 6 string = string.replace('+-','-') 7 string = string.replace('-+','-') 8 string = string.replace('--','+') 9 string = string.replace('*+','*') 10 string = string.replace('/+','/') 11 return string 12 #二、对于不符合要求的公式进行异常处理,给出错误提示信息 13 def check_expression(string): 14 check_result = True 15 if not string.count("(") == string.count(")"): 16 print('括号不对称') 17 check_result = False 18 if re.findall('[a-z]',string.lower()): 19 print('表达式有错,包含非法字符') 20 check_result = False 21 return check_result 22 #三、进行乘除运算,并将计算的结果替换掉原公式中的乘除法运算 23 def mul_div(string): 24 #正则表达式匹配(匹配乘除) 25 regular = '\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*' 26 #一直到公式中没有除法或乘法运算时,退出循环 27 while re.findall(regular,string):#注意:乘除法可以没有顺序 28 expression = re.search(regular,string).group() 29 # 计算乘法,并将计算的结果替换原来的式子 30 if expression.count('*'): 31 x,y=expression.split('*') 32 mul_result=str(float(x)*float(y)) 33 string=string.replace(expression,mul_result) 34 string=format_string(string) 35 # 计算除法,并将计算的结果替换原来的式子 36 elif expression.count('/'): 37 x, y = expression.split('/') 38 div_result = str(float(x) / float(y)) 39 string = string.replace(expression, div_result) 40 string = format_string(string) 41 return string 42 #四、进行加减法运算 43 def add_sub(string): 44 add_regu = '[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*' 45 sub_regu = '[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*' 46 # 计算加法,注意:加减法也可以没有顺序 47 while re.findall(add_regu,string): 48 add_list=re.findall(add_regu,string) 49 for add_str in add_list: 50 x, y = add_str.split("+") 51 add_result = str(float(x) + float(y)) 52 string = string.replace(add_str, add_result) 53 string = format_string(string) 54 while re.findall(sub_regu, string): 55 sub_list = re.findall(sub_regu, string) 56 for sub_str in sub_list: 57 numbers = sub_str.split('-') 58 # 计算开头为(-a-b)这种情况 59 if len(numbers) == 3: 60 result = 0 61 for v in numbers: 62 if v: 63 result -= float(v) 64 else: 65 x = numbers[0] 66 y = numbers[-1] 67 sub_result = float(x) - float(y) 68 string = string.replace(sub_str,str(sub_result)) 69 string = format_string(string) 70 return string 71 #五、主逻辑程序 72 info=True 73 while info: 74 source = input("请输入要计算的公式:") 75 if check_expression(source): 76 strs = format_string(source) 77 while source.count('(') > 0: 78 # 匹配最里层括号的内容 79 strs = re.search('\([^()]*\)', source).group()#在这里^是不包含的意思,[^()]+就是不包含括号的所有字符——返回最里面的括号 80 replace_str = mul_div(strs) 81 replace_str = add_sub(replace_str) 82 # 每次计算的结果去掉括号 83 source = format_string(source.replace(strs, replace_str[1:-1])) 84 # else下边的逻辑是计算不带括号的式子 85 else: 86 replace_str = mul_div(source) 87 replace_str = add_sub(replace_str) 88 source = source.replace(source, replace_str) 89 print(source) 90 signal=input("是否继续?y/n") 91 if signal=='y': 92 info=True 93 elif signal=='n': 94 info=False 95 print("已退出,欢迎下次使用!")
难点
1.匹配最里层括号的正则表达式:'\([^()]*\)'
2.匹配乘除法及加减法的正则表达式:
乘除——'\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
加——'[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
减——'[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'
3.主逻辑的设计
自我总结
此项目为借助已有代码所写;
相比基本语法,代码整体的逻辑设计更重要;
函数的思想还没有完全掌握;
代码的流程逻辑还需要提升;
其实代码也是模块化的,一个模块想清楚了,其他的也相似。
继续努力!
2019年5月7日