Python实现的复杂的计算器的代码

用Python实现复杂的计算器,可以按照“()”、乘除、加减的优先级进行混合运算。主旨是对正则表达式进行学习。

设计思路:

  1.在计算式中搜索最后一个“(”,再搜索和它匹配的“)”,截取两个括号间的表达式cul。

  2.乘除的优先级高,循环搜索cul内的乘除号,进行计算后进行加减计算,得到结果ans。

  3.用ans替换“(cul)”,重新搜索括号,知道将输入的公式简化成没有括号的四则运算。

  4.对最后的四则运算计算结果。流程图如下:

                                                                                                                      

设计时的注意事项:

  1.在简化计算式过程中,如3*(1-3),简化后为3*-2,在进行乘运算的时候会报错。解决措施为将乘数前的负号移至被乘数前。将算术式更换为-3*2。除法也用相同的方法处理。

  2.在出现“--”或“+-”的时候,可以把“--”替换成“+”,把“+-”替换成“-”。

代码分析:

代码的结构是这样的:

 

执行文件其实没啥说的!

1 import os,sys
2 BASE_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
3 print(BASE_dir)
4 sys.path.append(BASE_dir)
5 from core import main
6 if __name__ == '__main__':
7     main.run()

calculato.py就是将文件路径添加到环境变量中

 1 import re
 2 def mul(processor):      #乘运算
 3     a = re.search(r"(\d+)?[.]?(\d+)[*]", processor).group()[:-1]
 4     b = re.search(r"[*]\d+[.]?(\d+)?", processor).group()[1:]
 5     ans = float(a) * float(b)
 6     ans = str(ans)
 7     processor_past = re.sub(r"\d+[.]?(\d+)?[*]\d+[.]?(\d+)?", ans, processor, count=1)
 8     return processor_past
 9 def div(processor):        #除运算
10     a = re.search(r"(\d+)?[.]?(\d+)[/]", processor).group()[:-1]
11     b = re.search(r"[/]\d+[.]?(\d+)?", processor).group()[1:]
12     ans = float(a) / float(b)
13     ans = str(ans)
14     processor_past = re.sub(r"\d+[.]?(\d+)?[/]\d+[.]?(\d+)?", ans, processor, count=1)
15     return processor_past
16 def add(processor):      #加运算
17     a=re.search("(\d+)?[.]?(\d+)[+]",processor).group()[:-1]
18     b=re.search("[+]\d+[.]?(\d+)?",processor).group()[1:]
19     ans = float(a)+float(b)
20     ans = str(ans)
21     processor_past = re.sub(r"\d+[.]?(\d+)?[+]\d+[.]?(\d+)?",ans,processor,count=1)
22     return processor_past
23 def sub(processor):      #减运算
24     a=re.search("\d+[.]?(\d+)?[-]",processor).group()[:-1]
25     b=re.search("[-]\d+[.]?(\d+)?",processor).group()[1:]
26     ans = float(a)-float(b)
27     ans = str(ans)
28     processor_past = re.sub(r"\d+[.]?(\d+)?[-]\d+[.]?(\d+)?",ans,processor,count=1)
29     return processor_past

在func.py中定义了运算的方法,由于形参是字符串形式,需将计算结果转换成字符串,然后将结果和算术式替换:如mul("3*2+1)的返回值是“6+1”。

这里还用了字符串的切片方法,删掉第一个值:[1:],删掉最后一个值为[:-1]。

以乘法为例,"*"前必须为数字,被乘数是小数的话还会有小数点和整数位,所以在正则表达式的查询关键字为r“(\d+)?[.]?(\d+)[*]”,所引出字符串后删掉最后的“*”,而“*”后紧跟的是数字,小数点和小数点后的数为非必须字符。用r"[*]\d+[.]?(\d+)?"查找。

在查询关键字时“*"和”+“为转义字符,要在字符串前加”r“

 1 import re
 2 from core import func
 3 def find_brackets(cul):         #将“()”内表达式分析出来
 4     while re.search("[(].+", cul):
 5         cul = re.search("[(].+", cul).group()[1:]
 6     cul = cul[::-1]
 7     while re.search("[)].+", cul):
 8         cul = re.search("[)].+", cul).group()[1:]
 9     cul = cul[::-1]
10     return (cul)
11 
12 def change(search,ans,cul):                 #将运算结果和()里的表达式更换
13     search = re.sub("[+]", '\+',search)
14     search = re.sub("[*]", '\*',search)
15     cul = re.sub("[(]%s[)]"%search,ans,cul)#在正则表达式中插入变量
16     return cul
17 
18 def change_minus(search, ans, before):              # 和move_minus一起移动乘除号后面的负号
19     search = re.sub("[+]", '\+', search)
20     search = re.sub("[*]", '\*', search)
21     after = re.sub(search, ans, before)
22     return after
23 
24 def move_minus(cul):
25     b = cul
26     if re.search(r"(\d+)?[.]?\d+[*][-](\d+)?[.]?\d+?", cul):
27         a = re.search(r"(\d+)?[.]?\d+[*][-](\d+)?[.]?\d+?", cul).group()
28         c = a
29         a = re.sub("[-]", "", a)
30         a = '-' + a
31         b = change_minus(c, a, cul)
32     elif re.search(r"(\d+)?[.]?\d+[/][-](\d+)?[.]?\d+?", cul):
33         a = re.search(r"(\d+)?[.]?\d+[/][-](\d+)?[.]?\d+?", cul).group()
34         c = a
35         a = re.sub("[-]", "", a)
36         a = '-' + a
37         b = change_minus(c, a, cul)
38     return b
39 
40 
41 def mul_div(str_past):                                              #乘除优先级一致,进行乘除运算
42     ans = str_past
43     while re.search("[\*]|[/]",ans):
44         res = re.search("[/]|[\*]",ans).group()
45         if res == "*":
46             ans = func.mul(ans)
47         elif res =="/":
48             ans = func.div(ans)
49     return ans
50 
51 def add_reduce(str_past):                                           #加减优先级一致,进行加减运算
52     ans = str_past
53     ans = re.sub("--","+",ans)
54     ans = re.sub(r"[+][-]","-",ans)
55     while re.search(r"[+]|[-]",ans):
56         if re.match("-",ans):
57             break
58         else:
59             res = re.search(r"[+]|[-]",ans).group()
60             if res == "+":
61                 ans = func.add(ans)
62             elif res =="-":
63                 ans = func.sub(ans)
64     return ans
65 
66 def cul(str):
67     cul = str
68     ans = str
69     while re.search("[(]",cul):
70         cul = re.sub("--", "+", cul)
71         cul = re.sub(r"[+][-]", "-", cul)
72         cul_1 = find_brackets(cul)
73         ans = mul_div(cul_1)
74         ans = add_reduce(ans)
75         ans = change(cul_1,ans,cul)
76         cul = ans
77         cul = move_minus(cul)
78     ans = move_minus(ans)
79     ans = mul_div(ans)
80     ans = add_reduce(ans)
81     return ans

calcu.py定义了整个计算的流程。

cul()中不断索引括号,将索引出的算术式计算后用结论替代。每简化一轮后检查乘除号后是否有负号的状态。

 乘除法的优先级比加减高,可以把乘除的运算放在一起,

while re.search("[\*]|[/]",ans):

用这个方法可以从左到右循环搜索算术式内的乘除运算。

 1 import re
 2 import os,sys
 3 from core import calcu,func.log
 4 def run():
 5     print("欢迎使用计算器!!!")
 6     while True:
 7         cul = input("请输入计算公式:")
 8         if cul == "exit":
 9             print("退出计算器!")
10             break
11         elif re.findall("[(]", cul).__len__() != re.findall("[)]", cul).__len__():
12             print("括号不匹配!")
13         elif re.search("[(]|[)]",cul):
14             print("请使用英文符号!")
15         elif re.search("[a-z]|[A-Z]",cul):
16             print("请输入数字!")
17         else:
18             ans = calcu.cul(cul)
19             print(ans)
20             log.logger(cul,ans)

main.py调用了整个算式的计算过程,并对输入的公式进行了一些纠错措施并在每次计算后将计算式和结论存储在日志中。

1 import time
2 def logger(cul,ans):
3     fp = open("logger.txt",'a+',encoding="UTF-8")
4     now = time.time()
5     fp.write("%s     %s=%s\n"%(now,cul,ans))
6     fp.close()

log.py就是将每次运算的公式和结论存储在日志中。 

存在的问题:日志文件应存储在log路径下,但是现在每次执行完会在bin路径下生成新日志文件并进行存储操作。还在想办法改进中!

猜你喜欢

转载自www.cnblogs.com/yinsedeyinse/p/10010325.html