re模块之简单计算器的实现
本节大纲: ?
? 在我们学习re模块之后,通常的练习就是利用所学相关知识来写一个计算器 那么,现在我们开始理一下思路: 1.表达式的输入及检查、格式化1.1 输入首先呢,我们肯定要让用户先输入一个表达式 strs = input() ?1.2 检查之后,我们要做的就是检查所输入内容的合法性,这里我们用一个函数来封装 def check_str(s): # 检查字符串是否合法 flag = True 初始化假设字符串合法 if s.count("(") != s.count()"): 检查()是否个数相等 flag = False if re.search([a-zA-Z]",s): 检查是否出现了非法字符 flag = print("该表达式的合法性为:%s" % flag) return flag 所相应的匹配程序 while not check_str(strs): print(非法表达式!请重新输入") strs = input() 测试结果: IN:(1+1 OUT:非法表达式!请重新输入 IN:1+2p OUT:非法表达式!请重新输入 IN:2+3 当然,在上述代码中,非法字符的检测并不完善,这肯定需要改善,具体思路为: ?在我们输入表达式的时候,所输入的字符无非就如下几种情况:
所以我们只需做出相应的匹配即可 ? 1.3 格式化接下来我们要做的就是将表达式格式化---为了匹配的准确性 def format_str(s): 格式化字符串 s = s.replace(" "") s = s.replace(++++---+--/+/*+*) print("该表达式格式化后的结果为:%s" % s) return s ? 2.怎么样进行匹配最里面的括号以及操作数的匹配2.1.最里面的括号为什么要匹配最里面的括号呢? 当然是为了优先级啊 那么怎么匹配呢? import re strs = input() ret = re.search(([^()]+),strs) if ret: print(ret.group()) else: print(ret) ? ? ? 测试结果: IN:(1+(1+(1+1)))
OUT:(1+1)
IN:1+1
OUT:None
2.2 操作数的匹配我们的日常使用中操作数不仅仅只是整形,还有浮点型,所以我们需要考虑的就要多一点 -*-coding:utf-8 -*- re s =(?P<num1>d+(?:.d+)?)(?P<sign>[*/])(?P<num2>[+-]?d+(?:.d+)?)exp:%s"%ret.group()) num1:%s"%ret.group(num1)) sign:%ssignnum2:%snum2)) print(ret) ? ? ? 测试结果: IN:1*1 OUT:exp:1*1 num1:1 sign:* num2:1 IN:1.3/3.2 OUT:exp:1.3/3.2 num1:1.3 sign:/ num2:3.2 ? 3.四则运算3.1 乘除法在我们传递完最里面括号的内容后,我们要不断的匹配,计算,替换,直至最后没有括号 思路: 先一直循环,然后不断匹配符合要求的表达式,进行运算,替换,再匹配,直至匹配不到表达式,退出循环 re def div_mul(s): 进行表达式中乘或除的计算 while True: ret = re.search( 匹配乘或除的式子, 第二个操作数可以匹配符号,防止比如 1*-3匹配不到 第一个操作数没有匹配符号是因为防止 1-2*-3 --> 1 (-2*-3) --> 1 6 -->在下一个函数中成为 1+6 --> 7 的错误结果 ret = re.search("(?P<num1>d+(?:.d+)?)(?P<sign>[*/])(?P<num2>d+(?:.d+)?)",s) if not ret: ret = re.search("(?P<num1>d+(?:.d+)?)(?P<sign>[*/])(?P<num2>[+-]?d+(?:.d+)?)",s) if ret: 如果ret不为空就代表表达式中含有加或减的式子 exp = ret.group() 把表达式分离开来 num1 = ret.group(") 操作数1 num2 = ret.group( 操作数2 sign = ret.group( 运算符号 if sign == ": 乘法 result = float(num1) * float(num2) 除法 result = float(num1) /{}{}{}={}".format(num1,sign,num2,result)) 运行结果的打印 s = s.replace(exp,str(result)) 将计算结果替代表达式 else: 如果ret为空就代表该表达式中已经没有乘或除的式子了,就跳出循环 break s = format_str(s) # 格式化该字符串中的输出结果 return s s = input() print(div_mul(s)) 测试结果: IN:1+3*2-7*2
OUT:3*2=6.0
7*2=14.0
1+6.0-14.0
3.2 加减法思路: 将表达式中所有的数字分割为 一个操作数加上它前面的符号,最后对这些数进行统一的相加 re functools 测试结果: IN:1-2+3.2+1.7-5.2 OUT:['1',1)">-2+3.2+1.7-5.2'] -1.2999999999999998 -1.2999999999999998 ? ? 在这我们的四则运算也准备好了,最后我们要做的就是如何把表达式合理的送如四则运算中。 还是不断的进行运算、替换 值得一提的是,算完之后,我们要记得去其括号,进行下一个()的匹配 while re.search(( 如果还有()就进入循环 ret = re.search( 匹配最里面的() (ret): exp = ret.group() 进行表达式的分离 (exp) result = calc(exp) 进行表达式的计算 strs = strs.replace(exp,1)"> 表达式与结果的替换 strs = format_str(strs) 格式化 print(strs) ? ? 4.完整代码展示:-*- coding: UTF-8 -*- functools s flag break s = format_str(s) 格式化该字符串中的输出结果 def calc(s): 进行表达式的计算 s = div_mul(s) s = add_sub(s) s = s.replace("(","")#去括号 s = s.replace(")","") s = s.strip(() 去括号 该表达式计算后的结果为:%s" % s) def main(): strs = input() ) strs = input() strs = format_str(strs) (strs) strs = calc(strs) (strs) main() print(eval(1-2*((60-30 +(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40 / 5))-(-4*3)/(16-3*2)))) 1-2*((60-30 +(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40 / 5))-(-4*3)/(16-3*2)) # 2776672.6952380957 运行结果: IN: 1-2*((60-30 +(9-2*5/3+7/3*99/4*2998+10*568/14)*(-40 / 5))-(-4*3)/(16-3*2)) OUT:(9-2*5/3+7/3*99/4*2998+10*568/14) 2*5=10.0 10.0/3=3.3333333333333335 7/3=2.3333333333333335 2.3333333333333335*99=231.00000000000003 231.00000000000003/4=57.75000000000001 57.75000000000001*2998=173134.50000000003 10*568=5680.0 5680.0/14=405.7142857142857 [9-3.3333333333333335+173134.50000000003+405.7142857142857] 173545.88095238098 该表达式计算后的结果为:173545.88095238098 1-2*((60-30+173545.88095238098*(-40/5))-(-4*3)/(16-3*2)) (-40/5) 40/5=8.0-8.0] -8.0 该表达式计算后的结果为:-8.0 1-2*((60-30+173545.88095238098*-8.0)-(-4*3)/(16-3*2)) (60-30+173545.88095238098*-8.0) 173545.88095238098*-8.0=-1388367.047619047860-30-1388367.0476190478] -1388337.0476190478 该表达式计算后的结果为:-1388337.0476190478 1-2*(-1388337.0476190478-(-4*3)/(16-3*2)) (-4*3) 4*3=12.0-12.0] -12.0 该表达式计算后的结果为:-12.0 1-2*(-1388337.0476190478+12.0/(16-3*2)) (16-3*2) 3*2=6.016-6.0] 10.0 该表达式计算后的结果为:10.0 1-2*(-1388337.0476190478+12.0/10.0) (-1388337.0476190478+12.0/10.0) 12.0/10.0=1.2-1388337.0476190478+1.2] -1388335.8476190479 该表达式计算后的结果为:-1388335.8476190479 1-2*-1388335.8476190479 2*-1388335.8476190479=-2776671.6952380957+2776671.6952380957] 2776672.6952380957 该表达式计算后的结果为:2776672.6952380957 2776672.6952380957 2776672.6952380957 ? 在这,为了比对运算结果是否正确,笔者特地拿了 eval 进行计算,显然测试后:两结果相同 ? (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |