计算器实例
一、文字思路分析
拿到一个表达式,例如 ‘3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)’,通过这个表达式,我们除了考虑到数学的运算法则之外,还应该考虑到输入表达式过程存在的输入格式问题
1、格式问题:表达式中存在空格,就要去除空格
2、运算法则:有括号先去括号,先计算括号里面的没有括号的表达式;先算乘除再算加减;正负号问题,正负得负,负负得正
3、运用正则表达式去匹配表达式中的对应的项,然后计算
4、每一项计算出来都得反馈回那一项所在的地方
5、有重复的东西,需要用到循环
二、分模块进行计算(代码)
- 1、去空格模块
exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)' new_exp = exp.replace(' ','') print(new_exp)
运行结果:
3+(-80/2)+24*5-(18/3+4*(90/15-100)-3)
- 2、匹配和计算括号里面没有括号的项
先用正则表达式找出括号里面没有括号的项
ret = re.search('([^()]+)',new_exp) if ret: exp_no_bracket = ret.group() # 筛选出括号里面没有括号的表达式 print(exp_no_bracket)
运行结果:
(-80/2)
将括号里面没有括号的项去括号,然后找出单纯的乘除项,利用调用函数的方法,计算乘除结果
def cal_exp_no_bracket(ex): # ex是括号里面没有括号的项 ex = ex.strip('()') # 将里面没有括号的项的括号去除 # 计算先乘除后加减 ret = re.search('d+.?d*[*/]-?d+.?d*',ex) # 利用正则表达式找第一个出现的乘除的项 if ret: ex_son = ret.group() # 子表达式,最简单的只有乘除法 print(ex_son) ....
....
ret = cal_exp_no_bracket(exp_no_bracket) # 调用计算括号里面没有括号的函数
new_exp = new_exp.replace(exp_no_bracket,ret) # 将计算括号里面没有括号的最后的值代替对应的项
print(new_exp)
运行结果:
80/2
计算原子表达式,即最简的原子形式表达式
def cal_ex_son(ex_son): if '/' in ex_son: a,b, = ex_son.split('/') return str(float(a)/float(b)) elif '*' in ex_son: a,b, = ex_son.split('*') return str(float(a) * float(b)) ....
.... ret = cal_ex_son(ex_son) # 调用计算原子表达式的函数 print(ret) new_ex = ex.replace(ex_son,ret) # 将最终计算的值替代原来括号里面没有括号的那一项
运行结果应该是:
-40.0
3+-40.0+24*5-(18/3+4*(90/15-100)-3)
- 3、匹配和计算加减法
ret = re.findall('-?d+.?d*',ex) sum = 0 for i in ret: sum += float(i) return str(sum)
- 4、正负符号的处理
正负得负,负负得正
# 正负符号的处理,正负得负,负负得正 def dealwith(exp): exp = exp.replace('+-','-') exp = exp.replace('--','+') return exp ....
.... new_exp = dealwith(new_exp) print(new_exp)
运行结果应该是:
3-40.0+24*5-(18/3+4*(90/15-100)-3)
- 5、main程序
通过函数的调用和嵌套,一步一步计算
# 要计算的表达式 exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)' # 去空格 new_exp = exp.replace(' ','') print(new_exp) res = remove_bracket(new_exp) print(res)
三、计算器总模块代码
以上的2和3和4点只是计算了第一个匹配到括号里面没有括号的项,以及第一个出现乘除的项,和第一个出现加减法的项,要计算全部的这样的项,需要利用循环,去实现,主要式寻找和计算括号里面没有括号的项,还有寻找和计算简单的乘除以及加减式子需要反复寻找计算,最后整理的计算器的大致框架:
import re # 导入re模块,正则表达式需要 # 正负符号的处理,正负得负,负负得正 def dealwith(exp): exp = exp.replace('+-','-') exp = exp.replace('--','+') return exp # 计算原子形式的表达式,两个数的乘除法 def cal_ex_son(ex_son): if '/' in ex_son: a,b, = ex_son.split('/') return str(float(a)/float(b)) elif '*' in ex_son: a,b, = ex_son.split('*') return str(float(a)*float(b)) else: print('所有的乘除式子都计算好了') # 计算最简的括号里面没有括号的式子,先计算乘除法,再计算加减 def cal_exp_no_bracket(ex): # ex是括号里面没有括号的项 ex = ex.strip('()') # 将里面没有括号的项的括号去除 # 计算先乘除后加减 while True: # 利用循环找到括号里面不再有括号的项 ret = re.search('d+.?d*[*/]-?d+.?d*',ex) # 利用正则表达式找第一个出现的乘除的项 if ret: # 说明表达式中还有乘除法 ex_son = ret.group() # 子表达式,最简单的只有乘除法,原子形式 print('匹配到只有乘除法的项: ',ex_son) ret = cal_ex_son(ex_son) # 调用计算原子表达式的函数 ex = ex.replace(ex_son,ret) # 将最终计算的值替代原来括号里面没有括号的那一项 ex = dealwith(ex) else: # 说明表达式中没有乘除法,然后计算加减法 ret = re.findall('-?d+.?d*',ex) sum = 0 for i in ret: sum += float(i) return str(sum) # 筛选出括号里面没有括号的表达式,并且开始计算 def no_bracket_in_bracket(new_exp): while True: # 利用循环找到所有的一层一层里面没有括号的项 ret = re.search('([^()]+)',new_exp) if ret: exp_no_bracket = ret.group() # 筛选出括号里面没有括号的表达式 print('匹配到内部不再有括号的项: ',exp_no_bracket) ret = cal_exp_no_bracket(exp_no_bracket) # 调用计算括号里面没有括号的项 print(ret) new_exp = new_exp.replace(exp_no_bracket,ret) # 将计算括号里面没有括号的最后的值代替对应的项 new_exp = dealwith(new_exp) print(new_exp) else: print('表达式中没有括号了: ',new_exp) ret = cal_exp_no_bracket(new_exp) print(ret) break # 主程序,要计算的表达式 exp = '3+ (-80/2)+ 24*5-(18/3+ 4*(90/15-100) -3)' # 去空格 new_exp = exp.replace(' ','') print(new_exp) res = no_bracket_in_bracket(new_exp) print(res)
运行结果:
3+(-80/2)+24*5-(18/3+4*(90/15-100)-3) 匹配到内部不再有括号的项: (-80/2) 匹配到只有乘除法的项: 80/2 -40.0 3-40.0+24*5-(18/3+4*(90/15-100)-3) 匹配到内部不再有括号的项: (90/15-100) 匹配到只有乘除法的项: 90/15 -94.0 3-40.0+24*5-(18/3+4*-94.0-3) 匹配到内部不再有括号的项: (18/3+4*-94.0-3) 匹配到只有乘除法的项: 18/3 匹配到只有乘除法的项: 4*-94.0 -373.0 3-40.0+24*5+373.0 表达式中没有括号了: 3-40.0+24*5+373.0 匹配到只有乘除法的项: 24*5 456.0 None Process finished with exit code 0