• 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“

    下面是calcu.py的代码

     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
    "%(now,cul,ans))
    6     fp.close()

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

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


    感谢@callmeVcc的指正,上面的代码有一个BUG:

     按照上面的字符串输入,输出明显和需求不同,分析原因是因为在calcu.py中,我最开始的思路是在括号索引以后把纯加减乘除的计算过一遍,先过乘除,再过加减,但是在走加减的时候有个问题:

    如果字符串是2-1这种的,被减数是正数的情况,没什么问题,但是如果是负数,在上面第56行里,通过一个 if判断,如果字符串和-metch的话就退出循环,当时考虑不周,错误的思路如下:

    如果字符串里不含正负号,就是计算完毕,while循环跳出

    如果包含一个负号,就是计算结果为负数,while跳出

    但是-2+3这种情况也在if判断中也是为True的,遇到这种情况也会直接跳出while循环

    现在的思路就不用if判断了,直接从字符串的第2个元素开始匹配,就防止出现表达式第第一个数值为负数值无法跳出,

    在进行加减法运算的时候,取算数表达式左边的数值时要考虑到值为负的情形。

     1 """
     2 calcu.py
     3 """
     4 # Author:Aaron
     5 import re
     6 from . import func
     7 def find_brackets(cul):         #将“()”内表达式分析出来
     8     while re.search("[(].+", cul):
     9         cul = re.search("[(].+", cul).group()[1:]
    10     cul = cul[::-1]
    11     while re.search("[)].+", cul):
    12         cul = re.search("[)].+", cul).group()[1:]
    13     cul = cul[::-1]
    14     return (cul)
    15 
    16 def change(search,ans,cul):                 #将运算结果和()里的表达式更换
    17     search = re.sub("[+]", '+',search)
    18     search = re.sub("[*]", '*',search)
    19     cul = re.sub("[(]%s[)]"%search,ans,cul)  #在正则表达式中插入变量
    20     return cul
    21 
    22 def change_minus(search, ans, before):              # 和move_minus一起移动乘除号后面的负号
    23     search = re.sub("[+]", '+', search)
    24     search = re.sub("[*]", '*', search)
    25     after = re.sub(search, ans, before)
    26     return after
    27 
    28 def move_minus(cul):
    29     b = cul
    30     if re.search(r"(d+)?[.]?d+[*][-](d+)?[.]?d+?", cul):
    31         a = re.search(r"(d+)?[.]?d+[*][-](d+)?[.]?d+?", cul).group()
    32         c = a
    33         a = re.sub("[-]", "", a)
    34         a = '-' + a
    35         b = change_minus(c, a, cul)
    36     elif re.search(r"(d+)?[.]?d+[/][-](d+)?[.]?d+?", cul):
    37         a = re.search(r"(d+)?[.]?d+[/][-](d+)?[.]?d+?", cul).group()
    38         c = a
    39         a = re.sub("[-]", "", a)
    40         a = '-' + a
    41         b = change_minus(c, a, cul)
    42     return b
    43 
    44 
    45 def mul_div(str_past):                                              #乘除优先级一致,进行乘除运算
    46     ans = str_past
    47     while re.search("[*]|[/]",ans):
    48         res = re.search("[/]|[*]",ans).group()
    49         if res == "*":
    50             ans = func.mul(ans)
    51         elif res =="/":
    52             ans = func.div(ans)
    53     return ans
    54 
    55 def add_reduce(str_past):                                           #加减优先级一致,进行加减运算
    56     ans = str_past
    57     ans = re.sub("--","+",ans)
    58     ans = re.sub(r"[+][-]","-",ans)
    59     #下面的匹配是从字符串的第2个元素开始,防止字符串是以负数开头进入死循环
    60     while re.search(r"[+]|[-]",ans[1:]):
    61         res = re.search(r"[+]|[-]",ans[1:]).group()
    62         #表达式里包含加减号,按照从左到右的顺序依次计算
    63         if res == "+":
    64             ans = func.add(ans)
    65         elif res =="-":
    66             ans = func.sub(ans)
    67     #没有+-,返回值
    68     return ans
    69 
    70 def cul(str_input):
    71     cul = str_input
    72     ans = str_input
    73     while re.search("[(]",cul):
    74         cul = re.sub("--", "+", cul)
    75         cul = re.sub(r"[+][-]", "-", cul)
    76         cul_1 = find_brackets(cul)
    77         ans = mul_div(cul_1)
    78         ans = add_reduce(ans)
    79         ans = change(cul_1,ans,cul)
    80         cul = ans
    81         cul = move_minus(cul)
    82     ans = move_minus(ans)
    83     ans = mul_div(ans)
    84     ans = add_reduce(ans)
    85     return ans
    修改后的calcu.py
     1 """
     2 func.py
     3 """
     4 # Author:Aaron
     5 import re
     6 
     7 def mul(processor):
     8     a = re.search(r"(d+)?[.]?(d+)[*]", processor).group()[:-1]
     9     b = re.search(r"[*]d+[.]?(d+)?", processor).group()[1:]
    10     ans = float(a) * float(b)
    11     ans = str(ans)
    12     processor_past = re.sub(r"d+[.]?(d+)?[*]d+[.]?(d+)?", ans, processor, count=1)
    13     return processor_past
    14 
    15 def div(processor):
    16     a = re.search(r"(d+)?[.]?(d+)[/]", processor).group()[:-1]
    17     b = re.search(r"[/]d+[.]?(d+)?", processor).group()[1:]
    18     ans = float(a) / float(b)
    19     ans = str(ans)
    20     processor_past = re.sub(r"d+[.]?(d+)?[/]d+[.]?(d+)?", ans, processor, count=1)
    21     return processor_past
    22 
    23 def add(processor):
    24     a=re.search("[-]?(d+)[.]?(d+)?[+]",processor).group()[:-1]
    25     b=re.search("[+]d+[.]?(d+)?",processor).group()[1:]
    26 
    27     ans = float(a)+float(b)
    28     ans = str(ans)
    29 
    30     processor_past = re.sub(r"{}+{}".format(a,b),ans,processor,count=1)
    31 
    32     return processor_past
    33 
    34 def sub(processor):
    35     #a-b,获取a和b的值
    36     a=re.search("[-]?(d+)[.]?(d+)?[-]",processor).group()[:-1]
    37     b=re.search("[-]d+[.]?(d+)?",processor[1:]).group()[1:]   #获取b的值时候取巧,用对表达式进行切片防止拿到-1-2状态下的第一个负号后的值
    38     # print(a)
    39     # print(b)
    40     ans = float(a)-float(b)
    41     ans = str(ans)
    42 
    43     processor_past = re.sub(r"{}-{}".format(a,b),ans,processor,count=1)
    44     return processor_past
    修改后的func.py

    修改后的程序运行结论

  • 相关阅读:
    冲刺计划安排
    团队作业7——Alpha冲刺之事后诸葛亮
    团队作业6--展示博客(Alpha版本)
    团队作业5——测试与发布(Alpha版本)
    团队项目汇总
    【Java】五种常见排序之------------------快速排序
    【Java】五种常见排序之----------------归并排序
    【Java】五种常见排序之----------------------插入排序
    【Java】五种常见排序之---------选择排序
    【Java】五种常见排序之-----------冒泡排序
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/10010325.html
Copyright © 2020-2023  润新知