作业:利用正则表达式知识, 编辑一个简单的表达式计算器

烈酒焚心 提交于 2021-01-08 20:46:15

开发要求:

  开发一个简单的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,'*'),'\n')  # 输出欢迎界面
    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("输入表达式不合法,请重新检查")
 
 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!