zoukankan      html  css  js  c++  java
  • 作业:利用正则表达式知识, 编辑一个简单的表达式计算器

    开发要求:

      开发一个简单的python计算器:
      实现加减乘除及优先级解析;
      
      用户输入类似这样的表达式: 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.  功能分析:
        用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 这样的表达式,
        假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号,
        然后自己动手写代码解析其中的表达式,实现加减乘除,
        最后得出的结果与真实的计算机所算的结果必须一致。
     
    2.   所需要的知识点:
        1>  字符串的处理;
        2>  正则表达式的运用;
        3>  函数递归;
     
    3.   程序实现流程分析:
        1>  用正则表达式处理字符串,只提取其中的数字和运算符,并转换成列表
        2>  编写一个函数,处理没有括号的基本运算的基本表达式
        3>  再写一个函数递归处理带有括号的函数,先计算最内部括号中的表达式, 然后将最内部的括号替换为计算后的结果, 在递归外部一层的, 最后返回的就是所需的结果
     
    4.   具体实现过程:
     
     import re, sys
     def input_str():
        """
        输入表达式
        return: 返回有限的表达式
        """
        welcome_str = "超级计算器"
        print(welcome_str.center(50,'*'),' ')  # 输出欢迎界面
        while True:
           iput = input("请输入你要计算的表达式[q:退出]:").strip()
           if iput == 'q':  # 退出计算
              sys.exit("bye-bye")
           elif len(iput) == 0:
              continue
           else:
              iput = re.sub('s*', '', iput)  # 去除空格
              return iput
     
    def chengchu(expression):
        """
        乘除运算
        :param expression: 表达式
        :return: 返回没有乘除的表达式/最终的计算结果
        """
        val = re.search("d+.?d*[*/]+[+-]?d+.?d*", expression)            #匹配乘除号,能识别小数点和正负数,类似:['121.121*-121.12', '121/12.223', '3.4*4.5'];
        if not val:                                       #如果不存在乘除,就直接返回表达式;
           return expression
        else:
           data = re.search("d+.?d*[*/]+[+-]?d+.?d*", expression).group()
         if len(data.split("*")) > 1:                                    #以乘号分割
            part1, part2 = data.split("*")
            value = float(part1) * float(part2)
         else:
            part1, part2 = data.split("/")
            if float(part2) == 0:                                    #除数为0则为无效,退出
               sys.exit("除数为0,计算表达式失败!!!")
            value = float(part1) / float(part2)
     
        s1, s2 = re.split("d+.?d*[*/]+[+-]?d+.?d*", expression, 1)
        next_expression = "%s%s%s" % (s1, value, s2)
        return chengchu(next_expression)
     
    def jiajian(expression):
        """
        加减运算
        :param expression: 表达式
        :return: 返回没有计算的加减表达式/最终的计算结果
        """
        expression = expression.replace("+-", "-")                  # 替换表达式
        expression = expression.replace("--", "+")                  # 替换表达式
        expression = expression.replace("++", "+")                # 替换表达式
        expression = expression.replace("-+", "-")                  # 替换表达式
        val = re.search("-?d+.?d*[+-]{1}d+.?d*", expression)           # 匹配加减
        if not val:                                                                        # 如果不存在乘除,就直接返回表达式;
           return expression
        else:
           data = re.search("-?d+.?d*[+-]{1}d+.?d*", expression).group()
           if len(data.split("+")) > 1:                                    #以乘号分割
              part1, part2 = data.split("+")
              value = float(part1) + float(part2)
           elif data.startswith("-"):                                      #判断是否为负数开头
              part0, part1, part2 = data.split("-")
              value = -float(part1) - float(part2)
           else:
              part1, part2 = data.split("-")
              value = float(part1) - float(part2)
         s1, s2 = re.split("-?d+.?d*[+-]{1}d+.?d*", expression, 1)
         next_expression = "%s%s%s" % (s1, value, s2)
         return jiajian(next_expression)

     def remove_bracket(expression):
        """
        Function: 去小括号运算
        :param expression: 表达式
        :return: 结果
        """
        # 取最小括号内容:
        # 安组匹配,将括号内容按组匹配,过滤内容不存在括号即为最内层括号
        if not re.search(r"(([^()])+)", expression):                                   #判断小括号,如果不存在直接计算。
           ret1 = chengchu(expression)
           ret2 = jiajian(ret1)
           return ret2
        else:
           data = re.search(r"(([^()]+))", expression).group()        #取优先级最高的括号
           # '( 4+ 50 )'
           data = data.strip("[()]")                                                  #去掉括号,格式:strip([chars])
           # ' 4+ 50 '
           # 遵守先乘除后加减
           ret1 = chengchu(data)
           ret2 = jiajian(ret1)
           part1, replace_str, part2 = re.split(r"(([^()]+))", expression, 1)
           expression1 = "%s%s%s" % (part1, ret2, part2)                    # 将小括号的计算结果替换成表达式;
           return remove_bracket(expression1)

     if __name__ == "__main__":
        try:
           expression = input_str()
           # expression = "3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)"
           result = eval(expression)                           #用eval计算验证值;
           expression = expression.replace(" ", "")            #除了表达式中空格;
           ret = remove_bracket(expression)                    #用函数计算式得出的记过;
           result = float(result)
           ret = float(ret)
           if result == ret:                       #比较2种方式的计算结果,正确则输出结果
              print("eval计算结果: %s" % result)
              print("表达式计算结果: %s" % ret)
           else:                                   #不正确则提示异常,并返回结果
              print("计算结果异常,请重新检查!")
              print("eval计算结果: %s" % result)
              print("表达式计算结果: %s" % ret)
        except(SystemError, NameError, SyntaxError, ValueError, TypeError):
           print("输入表达式不合法,请重新检查")
     
     
  • 相关阅读:
    Lab IGMP
    IGMP知识要点
    15、通过例子讲解逻辑地址转换为物理地址的基本过程
    14、一个程序从开始运行到结束的完整过程,你能说出来多少?
    13、进程状态的切换你知道多少?
    12、虚拟技术你了解吗?
    11、动态分区分配算法有哪几种?可以分别说说吗?
    线程池
    10、内存交换和覆盖有什么区别?
    9、如果系统中具有快表后,那么地址的转换过程变成什么样了?
  • 原文地址:https://www.cnblogs.com/brace2011/p/9226468.html
Copyright © 2011-2022 走看看