用python实现计算1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))类似的公式计算

简介: 作业需求: 开发一个简单的python计算器 1、实现加减乘除及拓号优先级解析 2、用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自...

作业需求:

开发一个简单的python计算器

1、实现加减乘除及拓号优先级解析

2、用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致

上图是实现的逻辑思路图,下面是对上图的分析:

整体的思想就是先匹配最小的括号例如:1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) 从这个公式来看,应该先匹配到(-40/5),将这个括号里的公式进行计算,计算后将内容把(-40/5)替换掉,依次类推,将所有的括号都进行这样的计算与替换,在计算括号里的公式的时候需要注意的问题应该先匹配乘除进行计算与替换直到公式中没有乘除,然后再匹配加减进行计算与替换,直到匹配不到加减,这样最后的结果就是首先将括号里的内容计算并匹配,得到了一个只存在加减乘除的公式,这个时候和计算括号里的公式的方法一样,先匹配乘除计算并替换,然后匹配加减计算并替换,这样最后就能计算得出答案。

下列代码是整个的实现过程:注意:下面的代码并没有对输入公式的正确进行判断,但是已经实现了如果输入正确的公式都能正常计算

 1 import re
 2 #匹配整数或小数的乘除法,包括了开头存在减号的情况
 3 mul_div=re.compile("(-?\d+)(\.\d+)?(\*|/)(-?\d+)(\.\d+)?")
 4 #匹配整数或小数的加减法,包括了开头存在减号的情况
 5 plus_minus = re.compile("(-?\d+)(\.\d+)?(-|\+)(-?\d+)(\.\d+)?")
 6 #匹配括号
 7 bracket=re.compile("\([^()]*\)")
 8 #匹配乘法的时候出现乘以负数的情况,包括了开头存在减号的情况
 9 mul_minus_minus = re.compile("(-?\d+)(\.\d+)?(\*-)(\d+)(\.\d+)?")
10 #匹配除法的时候出现乘以负数的情况,包括了开头存在减号的情况
11 div_minus_minus = re.compile("(-?\d+)(\.\d+)?(/-)(\d+)(\.\d+)?")
12 
13 
14 #定义一个两位数的加减乘除法的运算,匹配左边的右边的数字和左边的数字,然后进行计算
15 def touble_cale(str_expire):
16     if str_expire.count("+") == 1:
17         right_num = float(str_expire[(str_expire.find("+")+1):])
18         left_num = float(str_expire[:str_expire.find("+")])
19         return str(right_num+left_num)
20     elif str_expire[1:].count("-") == 1:
21         right_num = float(str_expire[:str_expire.find("-",1)])
22         left_num = float(str_expire[(str_expire.find("-", 1) + 1):])
23         return str(right_num - left_num)
24     elif str_expire.count("*") == 1:
25         right_num = float(str_expire[:str_expire.find("*")])
26         left_num = float(str_expire[(str_expire.find("*")+1):])
27         return str(right_num * left_num)
28     elif str_expire.count("/") == 1:
29         right_num = float(str_expire[:str_expire.find("/")])
30         left_num = float(str_expire[(str_expire.find("/") + 1):])
31         return str(right_num / left_num)
32 
33 
34 #定义一个方法用于判断是否存在乘以负数和除以负数的情况
35 def judge_mul_minus(str_expire):
36     #判断公式中乘以负数的部分
37     if len(re.findall("(\*-)", str_expire)) != 0:
38         #调用上面的正则取得*-的公式
39         temp_mul_minus = mul_minus_minus.search(str_expire).group()
40         #将匹配的部分的*-换成*并将-放到前面
41         temp_mul_minus_2 = temp_mul_minus.replace(temp_mul_minus,"-" + temp_mul_minus.replace("*-","*"))
42         #经更改的的部分与原来的部分进行替换
43         str_expire=str_expire.replace(temp_mul_minus,temp_mul_minus_2)
44         return judge_mul_minus(str_expire)
45         #return str_expire
46     # 判断公式中除以负数的部分
47     elif len(re.findall(r"(/-)", str_expire)) != 0:
48         # 调用上面的正则取得/-的公式
49         temp_dev_minus = div_minus_minus.search(str_expire).group()
50         # 将匹配的部分的/-换成/并将-放到前面
51         temp_dev_minus_2 = temp_dev_minus.replace(temp_dev_minus,"-" + temp_dev_minus.replace("/-","/"))
52         # 经更改的的部分与原来的部分进行替换
53         str_expire = str_expire.replace(temp_dev_minus,temp_dev_minus_2)
54         return judge_mul_minus(str_expire)
55     #调用change_sign将公式中的++换成= +-换成-
56     return change_sign(str_expire)
57 
58 #定义一个方法取将--更改为+ +-改为-
59 def change_sign(str_expire):
60     if len(re.findall(r"(\+-)", str_expire)) != 0:
61         str_expire = str_expire.replace("+-", "-")
62         return change_sign(str_expire)
63     elif len(re.findall(r"(--)", str_expire)) != 0:
64         str_expire = str_expire.replace("--", "+")
65         return change_sign(str_expire)
66     return str_expire
67 
68 
69 #定义一个方法用于计算只有加减乘除的公式,优先处理乘法
70 def cale_mix(str_expire):
71     #如果公式中出现符号数字的情况即+5  -6 *8  /8的这种情况直接放回数字否则则先计算乘除在处理加减
72     while len(re.findall("[-+*/]",str_expire[1:])) != 0:
73         if len(re.findall("(\*|/)",str_expire)) != 0:
74             str_expire = str_expire.replace(mul_div.search(str_expire).group(),touble_cale(mul_div.search(str_expire).group()))
75         elif len(re.findall("(\+|-)",str_expire)) !=0:
76             str_expire = str_expire.replace(plus_minus.search(str_expire).group(),touble_cale(plus_minus.search(str_expire).group()))
77     return str_expire
78 
79 #定义一个方法用于去括号,并调用上述的方法进行计算
80 def remove_bracket(str_expire):
81     #判断公式中是否有括号
82     if len(bracket.findall(str_expire)) == 0:
83         return cale_mix(judge_mul_minus(str_expire))
84     elif len(bracket.findall(str_expire))!=0:
85         while len(bracket.findall(str_expire)) !=0:
86             #print(bracket.search(str_expire).group())
87             #只有存在括号优先处理括号中的内容并对内容进行替换,直到没有括号位置
88             str_expire = str_expire.replace(bracket.search(str_expire).group(),cale_mix(judge_mul_minus(bracket.search(str_expire).group()[1:-1])))
89         str_expire = cale_mix(judge_mul_minus(str_expire))
90         return str_expire
91 
92 
93 if __name__ == "__main__":
94     while True:
95         user_input_expire = input("请输入你的公式:(不要带空格,q表示退出):")
96         print("%s=%s" %(user_input_expire,remove_bracket(user_input_expire)))
97         continue

下面将代码进行分析:

首先是用写正则,一次匹配乘除法的正则,但是写的时候需要注意正则前面哟一个"-?",表示匹配乘除的时候需要匹配前面的减号。同样类似的方法匹配加减法,

然后是匹配括号,这个也是整个过程中非常重要的一个地方:bracket=re.compile("\([^()]*\)")

 接着是匹配乘以负数的情况已经除以负数的情况

 1 #匹配整数或小数的乘除法,包括了开头存在减号的情况
 2 mul_div=re.compile("(-?\d+)(\.\d+)?(\*|/)(-?\d+)(\.\d+)?")
 3 #匹配整数或小数的加减法,包括了开头存在减号的情况
 4 plus_minus = re.compile("(-?\d+)(\.\d+)?(-|\+)(-?\d+)(\.\d+)?")
 5 #匹配括号
 6 bracket=re.compile("\([^()]*\)")
 7 #匹配乘法的时候出现乘以负数的情况,包括了开头存在减号的情况
 8 mul_minus_minus = re.compile("(-?\d+)(\.\d+)?(\*-)(\d+)(\.\d+)?")
 9 #匹配除法的时候出现乘以负数的情况,包括了开头存在减号的情况
10 div_minus_minus = re.compile("(-?\d+)(\.\d+)?(/-)(\d+)(\.\d+)?")

接着下面的这个方法是用于匹配两位数的四则运算

 1 #定义一个两位数的加减乘除法的运算,匹配左边的右边的数字和左边的数字,然后进行计算
 2 def touble_cale(str_expire):
 3     if str_expire.count("+") == 1:
 4         right_num = float(str_expire[(str_expire.find("+")+1):])
 5         left_num = float(str_expire[:str_expire.find("+")])
 6         return str(right_num+left_num)
 7     elif str_expire[1:].count("-") == 1:
 8         right_num = float(str_expire[:str_expire.find("-",1)])
 9         left_num = float(str_expire[(str_expire.find("-", 1) + 1):])
10         return str(right_num - left_num)
11     elif str_expire.count("*") == 1:
12         right_num = float(str_expire[:str_expire.find("*")])
13         left_num = float(str_expire[(str_expire.find("*")+1):])
14         return str(right_num * left_num)
15     elif str_expire.count("/") == 1:
16         right_num = float(str_expire[:str_expire.find("/")])
17         left_num = float(str_expire[(str_expire.find("/") + 1):])
18         return str(right_num / left_num)

 

这个方法是用于判断存在乘以负数的时候和除以负数的情况如何处理,这里的操作是将负号放到公式的前面,然后将公式中的*-和/-都换成*和/

 1 #定义一个方法用于判断是否存在乘以负数和除以负数的情况
 2 def judge_mul_minus(str_expire):
 3     #判断公式中乘以负数的部分
 4     if len(re.findall("(\*-)", str_expire)) != 0:
 5         #调用上面的正则取得*-的公式
 6         temp_mul_minus = mul_minus_minus.search(str_expire).group()
 7         #将匹配的部分的*-换成*并将-放到前面
 8         temp_mul_minus_2 = temp_mul_minus.replace(temp_mul_minus,"-" + temp_mul_minus.replace("*-","*"))
 9         #经更改的的部分与原来的部分进行替换
10         str_expire=str_expire.replace(temp_mul_minus,temp_mul_minus_2)
11         return judge_mul_minus(str_expire)
12         #return str_expire
13     # 判断公式中除以负数的部分
14     elif len(re.findall(r"(/-)", str_expire)) != 0:
15         # 调用上面的正则取得/-的公式
16         temp_dev_minus = div_minus_minus.search(str_expire).group()
17         # 将匹配的部分的/-换成/并将-放到前面
18         temp_dev_minus_2 = temp_dev_minus.replace(temp_dev_minus,"-" + temp_dev_minus.replace("/-","/"))
19         # 经更改的的部分与原来的部分进行替换
20         str_expire = str_expire.replace(temp_dev_minus,temp_dev_minus_2)
21         return judge_mul_minus(str_expire)
22     #调用change_sign将公式中的++换成= +-换成-
23     return change_sign(str_expire)

下面的方法用于将公式中可能会出现++和--的情况,将其替换为++替换为+将--替换为+

1 #定义一个方法取将--更改为+ +-改为-
2 def change_sign(str_expire):
3     if len(re.findall(r"(\+-)", str_expire)) != 0:
4         str_expire = str_expire.replace("+-", "-")
5         return change_sign(str_expire)
6     elif len(re.findall(r"(--)", str_expire)) != 0:
7         str_expire = str_expire.replace("--", "+")
8         return change_sign(str_expire)
9     return str_expire

 

这个方法用于处理括号里面的四则运算以及整个公式没有括号,只剩下四则运算的情况,优先匹配乘除计算,如果没有乘除了匹配加减进行计算

1 #定义一个方法用于计算只有加减乘除的公式,优先处理乘法
2 def cale_mix(str_expire):
3     #如果公式中出现符号数字的情况即+5  -6 *8  /8的这种情况直接放回数字否则则先计算乘除在处理加减
4     while len(re.findall("[-+*/]",str_expire[1:])) != 0:
5         if len(re.findall("(\*|/)",str_expire)) != 0:
6             str_expire = str_expire.replace(mul_div.search(str_expire).group(),touble_cale(mul_div.search(str_expire).group()))
7         elif len(re.findall("(\+|-)",str_expire)) !=0:
8             str_expire = str_expire.replace(plus_minus.search(str_expire).group(),touble_cale(plus_minus.search(str_expire).group()))
9     return str_expire

 

下面的方法用于匹配括号用,匹配到括号后调用上面的方法进行计算和替换,直到整个公式计算完毕

 1 #定义一个方法用于去括号,并调用上述的方法进行计算
 2 def remove_bracket(str_expire):
 3     #判断公式中是否有括号
 4     if len(bracket.findall(str_expire)) == 0:
 5         return cale_mix(judge_mul_minus(str_expire))
 6     elif len(bracket.findall(str_expire))!=0:
 7         while len(bracket.findall(str_expire)) !=0:
 8             #print(bracket.search(str_expire).group())
 9             #只有存在括号优先处理括号中的内容并对内容进行替换,直到没有括号位置
10             str_expire = str_expire.replace(bracket.search(str_expire).group(),cale_mix(judge_mul_minus(bracket.search(str_expire).group()[1:-1])))
11         str_expire = cale_mix(judge_mul_minus(str_expire))
12         return str_expire
1 if __name__ == "__main__":
2     while True:
3         user_input_expire = input("请输入你的公式:(不要带空格,q表示退出):")
4         print("%s=%s" %(user_input_expire,remove_bracket(user_input_expire)))
5         continue

 

所有的努力都值得期许,每一份梦想都应该灌溉!
目录
相关文章
|
19天前
|
Python
【10月更文挑战第10天】「Mac上学Python 19」小学奥数篇5 - 圆和矩形的面积计算
本篇将通过 Python 和 Cangjie 双语解决简单的几何问题:计算圆的面积和矩形的面积。通过这道题,学生将掌握如何使用公式解决几何问题,并学会用编程实现数学公式。
150 60
|
29天前
|
Python
Datetime模块应用:Python计算上周周几对应的日期
Datetime模块应用:Python计算上周周几对应的日期
62 1
|
3月前
|
Python
Python 游泳秒表记次,计算每次游泳时长
Python 游泳秒表记次,计算每次游泳时长
50 2
|
3天前
|
机器学习/深度学习 算法 编译器
Python程序到计算图一键转化,详解清华开源深度学习编译器MagPy
【10月更文挑战第26天】MagPy是一款由清华大学研发的开源深度学习编译器,可将Python程序一键转化为计算图,简化模型构建和优化过程。它支持多种深度学习框架,具备自动化、灵活性、优化性能好和易于扩展等特点,适用于模型构建、迁移、部署及教学研究。尽管MagPy具有诸多优势,但在算子支持、优化策略等方面仍面临挑战。
8 3
|
14天前
|
Python
【10月更文挑战第15天】「Mac上学Python 26」小学奥数篇12 - 图形变换与坐标计算
本篇将通过 Python 和 Cangjie 双语实现图形变换与坐标计算。这个题目帮助学生理解平面几何中的旋转、平移和对称变换,并学会用编程实现坐标变化。
59 1
|
18天前
|
机器学习/深度学习 移动开发 Python
【10月更文挑战第11天】「Mac上学Python 22」小学奥数篇8 - 排列组合计算
本篇将通过 Python 和 Cangjie 双语讲解如何计算排列与组合。这道题目旨在让学生学会使用排列组合公式解决实际问题,并加深对数学知识和编程逻辑的理解。
56 4
|
17天前
|
数据可视化 Python
【10月更文挑战第12天】「Mac上学Python 23」小学奥数篇9 - 基础概率计算
本篇将通过 Python 和 Cangjie 双语实现基础概率的计算,帮助学生学习如何解决简单的概率问题,并培养逻辑推理和编程思维。
43 1
|
1月前
|
机器学习/深度学习 并行计算 大数据
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧2
【Python篇】NumPy完整指南(上篇):掌握数组、矩阵与高效计算的核心技巧
60 10
|
30天前
|
数据挖掘 iOS开发 MacOS
利用Python计算农历日期
利用Python计算农历日期
61 4
|
28天前
|
存储 自然语言处理 数据处理
使用Python计算多个集合的交集详解
使用Python计算多个集合的交集详解
28 1