一、功能分析
日常生活中我们用的计算器都包括加减乘除幂平方立方1 - 2 * ( (60-30 +(-9**5-2-5-2*-3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )这么这么长的一个式子,大家算的时候都知道先算幂,立方,平方,再算乘除,加减
二、知识点
所用到的python的知识点有:
-
正则表达式re模块
-
字符串的处理
三、程序实现流程分析
-
用正则表达式处理字符串,只提取其中的数字和运算符,并转换成列表
-
编写一个函数,处理没有括号的基本运算的基本表达式
-
再写一个函数递归处理带有括号的函数,先计算最内部括号中的表达式, 然后将最内部的括号替换为计算后的结果, 在递归外部一层的, 最后返回的就是所需的结果
四、代码部分
上面也说了处理的时候先处理幂,平方,立方
1、处理幂函数
import re,sys def Power(arg): ''' 计算幂函数 :param arg: 传进来的等式 :return: 返回计算完的等式 ''' while True: relust = re.split(r"(d+.?d*[*/]{2}-?d+.?d*)", arg, 1) if len(relust) == 3: # 判断切割出来的是不是3个元素 before = relust[0] # 第一个元素赋值给before content = relust[1] # 第二个元素赋值给content after = relust[2] if "**" in content: #如果等式里面有“**” start,end = content.split("**") #用**吧分割开 finlly = float(start) ** float(end) #计算幂等式 arg = before + str(finlly) + after #把结果替换回原等式 else: return arg
2、处理乘除
从左往右的时候不能先算乘,必须遇到乘就算乘遇到除就算除,楼主在这踩过坑,所以大家也注意下:
def Multply_didvid(arg): #定义乘除运算的函数 ''' 计算加减 :param arg: 传进来的算法 :return: 返回运算结果 ''' while True: #while循环每一次传进来的运算 arg = re.sub(r"++","+",arg) arg = re.sub(r"+-", "-", arg) arg = re.sub(r"-+", "-", arg) arg = re.sub(r"--", "+", arg) relust = re.split(r"(d+.?d*[*/]-?d+.?d*)",arg,1) #把从左往右第一次匹配到得乘法 # print(relust) if len(relust) ==3: #判断切割出来的是不是3个元素 before = relust[0] #第一个元素赋值给before content = relust[1] #第二个元素赋值给content after = relust[2] #第三个元素赋值给after if "*" in content: #判断第二个元素里面有没有"*" start,end = content.split("*") #用“*”把分割开赋值给start,end finlly = float(start) * float(end) #运算出乘法 arg = before+str(finlly)+after #替换原来的运算式 else: #否则就是除法 start, end = content.split("/") #用/分割开赋值给start,end finlly = float(start) / float(end) #把除法算出来 arg = before + str(finlly) + after #替换原来的元算是 # print(arg) else: return arg #将运算结果返回去
3、处理加减
加减是最简单的,把每个数字带前面的符号给切割出来,然后给定义一个计数器,依次相加就可得出结果
def Add_sub(arg): #加减法运算-9-2-5-2+5-3 ''' 计算加减运算 :param arg: 传进来的算术 :return: 返回运算结果 ''' result = re.findall(r"[+-]?d+.?d*",arg) #列出所有的元素 start = 0 #定义空值让他挨个去加 for i in result: start += float(i) #让素有元素相加 return start #返回运算结果
4、式子处理函数
拿到式子,我们肯定是先处理式子,把有括号得拿出来处理
def Calculate(source): ''' 计算函数 :param source: 传进来的等式 :return: 返回计算结果 ''' while True: source = re.sub(r"s*", "", source) #去掉空格 source = source.replace("++","+").replace("+-","-").replace("--","+").replace("-+","-") #替换符号 res = re.split(r"(([^()]+))",source,1) #先取出括号里面的值 if len(res) ==3: #判断分割出来的是不是3个元素 before = res[0] #分别将元素赋值给三个值 content = res[1] after = res[2] powe = Power(content) mu_di = Multply_didvid(powe) #执行乘除 ad_su = Add_sub(mu_di) #执行加减 res = before + str(ad_su) + after #运算结果替换原来等式 source = res #赋值给其他传进来元素 #print("去括号得到得值为:",source) else: powe = Power(source) mu_di = Multply_didvid(powe) #没括号得等式 ad_su = Add_sub(mu_di) #计算加法 source = ad_su # print('最后结果为:',ad_su) #打印最后结果 return source
到这里为止,代码就可以算是完成了,下面把代码总和起来,可以运行试试看:
import re,sys def Power(arg): ''' 计算幂函数 :param arg: 传进来的等式 :return: 返回计算完的等式 ''' while True: relust = re.split(r"(d+.?d*[*/]{2}-?d+.?d*)", arg, 1) if len(relust) == 3: # 判断切割出来的是不是3个元素 before = relust[0] # 第一个元素赋值给before content = relust[1] # 第二个元素赋值给content after = relust[2] if "**" in content: #如果等式里面有“**” start,end = content.split("**") #用**吧分割开 finlly = float(start) ** float(end) #计算幂等式 arg = before + str(finlly) + after #把结果替换回原等式 else: return arg def Multply_didvid(arg): #定义乘除运算的函数 ''' 计算加减 :param arg: 传进来的算法 :return: 返回运算结果 ''' while True: #while循环每一次传进来的运算 arg = re.sub(r"++","+",arg) arg = re.sub(r"+-", "-", arg) arg = re.sub(r"-+", "-", arg) arg = re.sub(r"--", "+", arg) relust = re.split(r"(d+.?d*[*/]-?d+.?d*)",arg,1) #把从左往右第一次匹配到得乘法 # print(relust) if len(relust) ==3: #判断切割出来的是不是3个元素 before = relust[0] #第一个元素赋值给before content = relust[1] #第二个元素赋值给content after = relust[2] #第三个元素赋值给after if "*" in content: #判断第二个元素里面有没有"*" start,end = content.split("*") #用“*”把分割开赋值给start,end finlly = float(start) * float(end) #运算出乘法 arg = before+str(finlly)+after #替换原来的运算式 else: #否则就是除法 start, end = content.split("/") #用/分割开赋值给start,end finlly = float(start) / float(end) #把除法算出来 arg = before + str(finlly) + after #替换原来的元算是 # print(arg) else: return arg #将运算结果返回去 def Add_sub(arg): #加减法运算-9-2-5-2+5-3 ''' 计算加减运算 :param arg: 传进来的算术 :return: 返回运算结果 ''' result = re.findall(r"[+-]?d+.?d*",arg) #列出所有的元素 start = 0 #定义空值让他挨个去加 for i in result: start += float(i) #让素有元素相加 return start #返回运算结果 def Calculate(source): ''' 计算函数 :param source: 传进来的等式 :return: 返回计算结果 ''' while True: source = re.sub(r"s*", "", source) #去掉空格 source = source.replace("++","+").replace("+-","-").replace("--","+").replace("-+","-") #替换符号 res = re.split(r"(([^()]+))",source,1) #先取出括号里面的值 if len(res) ==3: #判断分割出来的是不是3个元素 before = res[0] #分别将元素赋值给三个值 content = res[1] after = res[2] powe = Power(content) mu_di = Multply_didvid(powe) #执行乘除 ad_su = Add_sub(mu_di) #执行加减 res = before + str(ad_su) + after #运算结果替换原来等式 source = res #赋值给其他传进来元素 #print("去括号得到得值为:",source) else: powe = Power(source) mu_di = Multply_didvid(powe) #没括号得等式 ad_su = Add_sub(mu_di) #计算加法 source = ad_su # print('最后结果为:',ad_su) #打印最后结果 return source print(' ****************************************************************') print(' 33[33m 欢迎使用计算器(^-_-^) 33[0m') print(' ****************************************************************') print("计算等式直接复制即可!:","1 - 2 * ( (60-30 +(-9**5-2-5-2*-3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )") while True: inp = input("请输入计算等式(q退出):") if inp =="q": sys.exit("欢迎下次光临!") elif not inp.strip(): inp = inp.strip() continue else: fin = Calculate(inp) print("计算结果为:%s" % fin) print("eval结果为:%s" % eval(inp))
五:总结
死是不是发现还有点复杂,我相信大家还能写出更简单的,当然python为了追求简单,一行代码也可以搞定,eval()函数直接搞定,但是自己写下好提高自己的能力嘛,嘿嘿