zoukankan      html  css  js  c++  java
  • Python之计算器

    作业:

         使用正则表达式和递归实现计算器功能。

     实现:

           1、实现带括号的计算

           2、实现指数、加减乘除求余取整等功能


    1、实现思路

      1.1 先查找括号,有括号则递归计算括号内的结果。无括号则直接计算表达式

      1.2 使用正则表达式匹配字符串,用计算结果替换计算的表达式。

    2、流程图

    3、测试效果

      计算器对于测试输入做了校验。比如输入 '-2 - / 3' 、 '2 + * 3' 、 '-3 +-' 等等

    4、源码实现

      1 #!/usr/bin/env python3
      2 # -*- coding:utf-8 -*-
      3 # Version:Python3.5.0
      4 import re
      5 
      6 def check_exp(get_input):
      7     '''
      8     输入一个表达式,判断是否正确,返回一个去空格的表达式
      9     :param get_input: 获取的表达式
     10     :return: 返回一个去空格的表达式
     11     '''
     12     char_set = set(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     13                     '+', '-', '*', '/', '%', '//', '**', '.', '(', ')'))       # 有效表达式的字符集合
     14     # 判断输入的字符合法,输入的表达式字符属于全集char_set为真
     15     if set(get_input).issubset(char_set):
     16         # 输入的表达式是乘号'*'、除号'/',百分号'%' 开头的,不合法
     17         if get_input.startswith('*') or get_input.startswith('/') or get_input.startswith('%'):
     18             print('33[31;1m输入的表达式不正确,请重新输入!33[0m')
     19             return False
     20         # 输入的表达式是乘号'*'、除号'/',百分号'%'、加号'+'、减号'-' 结尾的,不合法
     21         elif (get_input.endswith('*') or get_input.endswith('/') or get_input.endswith('%')
     22                 or get_input.endswith('+') or get_input.endswith('-')):
     23             print('33[31;1m输入的表达式不正确,请重新输入!33[0m')
     24             return False
     25         # 输入的表达式中,有两个点号或者加减号后面跟着乘除百分号的,不合法
     26         elif ('..' in get_input or '+*' in get_input or '+/' in get_input or '+%' in get_input
     27                 or '-*' in get_input or '-/' in get_input or '-%' in get_input):
     28             print('33[31;1m输入的表达式不正确,请重新输入!33[0m')
     29             return False
     30         else:
     31             return True
     32     else:
     33         print('33[31;1m输入的表达式包涵其他字符,无法进行计算,请重新输入!33[0m')
     34         return False
     35 
     36 def replace_symbol(exp):
     37     '''
     38     化简表达式,比如“++-”转换成“-",返回最简表达式
     39     :param exp: 需要化简的表达式
     40     :return:    化简后的表达式
     41     '''
     42     # 初始化一个替换字符的列表
     43     replace_char_list = [('+-', '-'), ('-+', '-'), ('++', '+'), ('--', '+'), ('*+', '*'),
     44                         ('/+', '/'), ('%+', '%'), ('//+', '//'), ('**+', '**')]
     45     flag = False    # 初始化标识符
     46     count = 0       # 初始化不匹配次数
     47     while not flag:
     48         for i in replace_char_list:
     49             if i[0] in exp:    # 要化简的字符在表达式中,则直接替换
     50                 exp = exp.replace(i[0], i[1])   # 把需要替换的键字符串修改为其值的字符串
     51                 break     # 中断for循环,进行下一次while循环
     52             else:
     53                 count += 1
     54             # 当count等于 len(replace_char_list)时,即 没有需要替换的字符了,退出循环
     55             if count == len(replace_char_list):
     56                 flag = True
     57 
     58         if exp.startswith('+'):
     59             exp = exp[1:]   # 除去表达式中开头的加号
     60     return exp
     61 
     62 def parenthesis(exp):
     63     '''
     64     运算括号里面的表达式,运算结果替代括号的内容,返回运算结果
     65     :param exp: 计算的表达式
     66     :return: None
     67     '''
     68     match = re.search('(([+-*/%//**]*d+.*d*){2,})', exp)  # 匹配括号内的表达式
     69     if match:   # 找到匹配的字符
     70         content = match.group()[1:-1]     # 获取匹配到的表达式,并过滤括号
     71         result = calculate(content)     # 调用计算函数,返回结束结果
     72         print('计算前的表达式:33[32;1m%s33[0m' % exp)
     73         print('括号中运算结果:33[33;1m%s=%s33[0m' % (content, result))
     74         replace_content = '(' + content + ')'
     75         exp = exp.replace(replace_content, result)      # 把运算结果替换表达式
     76         exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
     77         print('计算后的表达式:33[34;1m%s33[0m
    ' % exp)
     78         parenthesis(exp)     # 递归执行括号处理
     79     else:
     80         result = calculate(exp)  # 当表达式没有括号时,直接计算表达式结果
     81         print('表达式运算结果:33[35;1m%s33[0m' % result)
     82 
     83 def power(exp):
     84     '''
     85     幂运算,返回运算结果
     86     :param exp: 幂运算的表达式
     87     :return: 计算后的表达式
     88     '''
     89     match = re.search('d+.?d*[*]{2}[+-]*d+.?d*', exp)  # 匹配幂运算
     90     if match:   # 找到匹配的字符
     91         content = match.group()     # 获取匹配到的表达式
     92         if len(content.split('**')) > 1:
     93             n1, n2 = content.split('**')
     94             value = float(n1) ** float(n2)
     95             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
     96             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
     97             return power(exp)      # 递归重复匹配
     98         else:
     99             pass
    100     else:
    101         return exp  # 不匹配到,返回exp
    102 
    103 def mul_div(exp):
    104     '''
    105     做乘法、除法、取余、取整运算,返回运算结果
    106     :param exp: 乘法、除法、取余、取整运算的表达式
    107     :return: 计算后的表达式
    108     '''
    109     match = re.search('d+.?d*[*/%//]+[+-]?d+.?d*', exp)  # 匹配乘、除、取余、取整运算
    110     if match:   # 找到匹配的字符
    111         content = match.group()     # 获取匹配到的表达式
    112         if len(content.split('*')) > 1:
    113             n1, n2 = content.split('*')
    114             value = float(n1) * float(n2)   # 乘法运算
    115             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    116             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    117             return mul_div(exp)
    118 
    119         elif len(content.split('//')) > 1:
    120             n1, n2 = content.split('//')     # 取余运算
    121             value = float(n1) // float(n2)
    122             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    123             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    124             return mul_div(exp)
    125 
    126         elif len(content.split('%')) > 1:
    127             n1, n2 = content.split('%')     # 除法运算
    128             value = float(n1) % float(n2)
    129             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    130             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    131             return mul_div(exp)
    132 
    133         elif len(content.split('/')) > 1:
    134             n1, n2 = content.split('/')    # 取整运算
    135             value = float(n1) / float(n2)
    136             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    137             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    138             return mul_div(exp)
    139 
    140         else:
    141             pass
    142     else:
    143         return exp  # 不匹配到,返回exp
    144 
    145 def add_sub(exp):
    146     '''
    147     加法、减法运算,返回运算结果
    148     :param exp: 加法、减法运算的表达式
    149     :return: 计算后的表达式
    150     '''
    151     match = re.search('-?d+.?d*[+-]+d+.?d*', exp)  # 匹配加法、减法
    152     if match:   # 找到匹配的字符
    153         content = match.group()     # 获取匹配到的表达式
    154         if len(content.split('+')) > 1:
    155             n1, n2 = content.split('+')
    156             value = float(n1) + float(n2)
    157             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    158             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    159             return add_sub(exp)
    160 
    161         elif len(content.split('-')) > 1:
    162             if len(content.split('-')) == 3:    # 被减数是负数的情况
    163                 n1, n2 = content.split('-')[1:]     #  过滤分割列表开头的空白字符串
    164                 value = float('-' + n1) - float(n2)   # 被减数需要添加一个负号
    165                 exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    166                 exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    167                 return add_sub(exp)
    168             elif len(content.split('-')) == 2:    # 被减数是正数的情况
    169                 n1, n2 = content.split('-')     #  直接把两个操作数赋值给对应的变量
    170                 value = float(n1) - float(n2)   # 做减法运算
    171                 exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    172                 exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    173                 return add_sub(exp)
    174             else:
    175                 pass
    176         else:
    177             pass
    178     else:
    179         return exp  # 不匹配到,返回exp
    180 
    181 def calculate(exp):
    182     '''
    183     获取一个运算表达式,返回运算结果
    184     :param exp: 表达式
    185     :return: 运算结果
    186     '''
    187     result = power(exp)         # 执行幂运算,返回运算结果
    188     result = mul_div(result)    # 执行乘法、除法、取余、取整运算,返回运算结果
    189     result = add_sub(result)    # 执行加法、减法运算,返回运算结果
    190     return result
    191 
    192 if __name__ == '__main__':
    193     print('33[31;1m欢迎使用计算器33[0m'.center(100,'='))
    194     while True:
    195         # 计算 s = '1-2 *(   (60- 30+(-40.0/5)*(9-2*5 / 3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
    196         get_input = input('
    33[32;1m请输入一个表达式 | 退出(q): 33[0m').strip()
    197         get_input = ''.join(re.split('s+', get_input))    # 除去输入表达式中多余的空格
    198         if get_input == '':     # 空字符,重新输入
    199             continue
    200         elif get_input == 'q':
    201             print('33[31;1m退出程序!33[0m')
    202             break
    203         elif check_exp(get_input):    # 输入的表达式合法
    204             exp = replace_symbol(get_input)     # 化简输入的表达式
    205             print('化简后的表达式:33[33;1m%s33[0m
    ' % exp)
    206             parenthesis(exp)
    207         else:
    208             pass
    计算器_python35
      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 # Version:Python2.7.10
      4 import re
      5 
      6 def check_exp(get_input):
      7     '''
      8     输入一个表达式,判断是否正确,返回一个去空格的表达式
      9     :param get_input: 获取的表达式
     10     :return: 返回一个去空格的表达式
     11     '''
     12     char_set = set(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     13                     '+', '-', '*', '/', '%', '//', '**', '.', '(', ')'))       # 有效表达式的字符集合
     14     # 判断输入的字符合法,输入的表达式字符属于全集char_set为真
     15     if set(get_input).issubset(char_set):
     16         # 输入的表达式是乘号'*'、除号'/',百分号'%' 开头的,不合法
     17         if get_input.startswith('*') or get_input.startswith('/') or get_input.startswith('%'):
     18             print(u'33[31;1m输入的表达式不正确,请重新输入!33[0m')
     19             return False
     20         # 输入的表达式是乘号'*'、除号'/',百分号'%'、加号'+'、减号'-' 结尾的,不合法
     21         elif (get_input.endswith('*') or get_input.endswith('/') or get_input.endswith('%')
     22                 or get_input.endswith('+') or get_input.endswith('-')):
     23             print(u'33[31;1m输入的表达式不正确,请重新输入!33[0m')
     24             return False
     25         # 输入的表达式中,有两个点号或者加减号后面跟着乘除百分号的,不合法
     26         elif ('..' in get_input or '+*' in get_input or '+/' in get_input or '+%' in get_input
     27                 or '-*' in get_input or '-/' in get_input or '-%' in get_input):
     28             print(u'33[31;1m输入的表达式不正确,请重新输入!33[0m')
     29             return False
     30         else:
     31             return True
     32     else:
     33         print(u'33[31;1m输入的表达式包涵其他字符,无法进行计算,请重新输入!33[0m')
     34         return False
     35 
     36 def replace_symbol(exp):
     37     '''
     38     化简表达式,比如“++-”转换成“-",返回最简表达式
     39     :param exp: 需要化简的表达式
     40     :return:    化简后的表达式
     41     '''
     42     # 初始化一个替换字符的列表
     43     replace_char_list = [('+-', '-'), ('-+', '-'), ('++', '+'), ('--', '+'), ('*+', '*'),
     44                         ('/+', '/'), ('%+', '%'), ('//+', '//'), ('**+', '**')]
     45     flag = False    # 初始化标识符
     46     count = 0       # 初始化不匹配次数
     47     while not flag:
     48         for i in replace_char_list:
     49             if i[0] in exp:    # 要化简的字符在表达式中,则直接替换
     50                 exp = exp.replace(i[0], i[1])   # 把需要替换的键字符串修改为其值的字符串
     51                 break     # 中断for循环,进行下一次while循环
     52             else:
     53                 count += 1
     54             # 当count等于 len(replace_char_list)时,即 没有需要替换的字符了,退出循环
     55             if count == len(replace_char_list):
     56                 flag = True
     57 
     58         if exp.startswith('+'):
     59             exp = exp[1:]   # 除去表达式中开头的加号
     60     return exp
     61 
     62 def parenthesis(exp):
     63     '''
     64     运算括号里面的表达式,运算结果替代括号的内容,返回运算结果
     65     :param exp: 计算的表达式
     66     :return: None
     67     '''
     68     match = re.search('(([+-*/%//**]*d+.*d*){2,})', exp)  # 匹配括号内的表达式
     69     if match:   # 找到匹配的字符
     70         content = match.group()[1:-1]     # 获取匹配到的表达式,并过滤括号
     71         result = calculate(content)     # 调用计算函数,返回结束结果
     72         print(u'计算前的表达式:33[32;1m%s33[0m' % exp)
     73         print(u'括号中运算结果:33[33;1m%s=%s33[0m' % (content, result))
     74         replace_content = '(' + content + ')'
     75         exp = exp.replace(replace_content, result)      # 把运算结果替换表达式
     76         exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
     77         print(u'计算后的表达式:33[34;1m%s33[0m
    ' % exp)
     78         parenthesis(exp)     # 递归执行括号处理
     79     else:
     80         result = calculate(exp)  # 当表达式没有括号时,直接计算表达式结果
     81         print(u'表达式运算结果:33[35;1m%s33[0m' % result)
     82 
     83 def power(exp):
     84     '''
     85     幂运算,返回运算结果
     86     :param exp: 幂运算的表达式
     87     :return: 计算后的表达式
     88     '''
     89     match = re.search('d+.?d*[*]{2}[+-]*d+.?d*', exp)  # 匹配幂运算
     90     if match:   # 找到匹配的字符
     91         content = match.group()     # 获取匹配到的表达式
     92         if len(content.split('**')) > 1:
     93             n1, n2 = content.split('**')
     94             value = float(n1) ** float(n2)
     95             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
     96             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
     97             return power(exp)      # 递归重复匹配
     98         else:
     99             pass
    100     else:
    101         return exp  # 不匹配到,返回exp
    102 
    103 def mul_div(exp):
    104     '''
    105     做乘法、除法、取余、取整运算,返回运算结果
    106     :param exp: 乘法、除法、取余、取整运算的表达式
    107     :return: 计算后的表达式
    108     '''
    109     match = re.search('d+.?d*[*/%//]+[+-]?d+.?d*', exp)  # 匹配乘、除、取余、取整运算
    110     if match:   # 找到匹配的字符
    111         content = match.group()     # 获取匹配到的表达式
    112         if len(content.split('*')) > 1:
    113             n1, n2 = content.split('*')
    114             value = float(n1) * float(n2)   # 乘法运算
    115             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    116             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    117             return mul_div(exp)
    118 
    119         elif len(content.split('//')) > 1:
    120             n1, n2 = content.split('//')     # 取余运算
    121             value = float(n1) // float(n2)
    122             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    123             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    124             return mul_div(exp)
    125 
    126         elif len(content.split('%')) > 1:
    127             n1, n2 = content.split('%')     # 除法运算
    128             value = float(n1) % float(n2)
    129             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    130             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    131             return mul_div(exp)
    132 
    133         elif len(content.split('/')) > 1:
    134             n1, n2 = content.split('/')    # 取整运算
    135             value = float(n1) / float(n2)
    136             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    137             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    138             return mul_div(exp)
    139 
    140         else:
    141             pass
    142     else:
    143         return exp  # 不匹配到,返回exp
    144 
    145 def add_sub(exp):
    146     '''
    147     加法、减法运算,返回运算结果
    148     :param exp: 加法、减法运算的表达式
    149     :return: 计算后的表达式
    150     '''
    151     match = re.search('-?d+.?d*[+-]+d+.?d*', exp)  # 匹配加法、减法
    152     if match:   # 找到匹配的字符
    153         content = match.group()     # 获取匹配到的表达式
    154         if len(content.split('+')) > 1:
    155             n1, n2 = content.split('+')
    156             value = float(n1) + float(n2)
    157             exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    158             exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    159             return add_sub(exp)
    160 
    161         elif len(content.split('-')) > 1:
    162             if len(content.split('-')) == 3:    # 被减数是负数的情况
    163                 n1, n2 = content.split('-')[1:]     #  过滤分割列表开头的空白字符串
    164                 value = float('-' + n1) - float(n2)   # 被减数需要添加一个负号
    165                 exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    166                 exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    167                 return add_sub(exp)
    168             elif len(content.split('-')) == 2:    # 被减数是正数的情况
    169                 n1, n2 = content.split('-')     #  直接把两个操作数赋值给对应的变量
    170                 value = float(n1) - float(n2)   # 做减法运算
    171                 exp = exp.replace(content, str(value))   # 用计算的结果替换计算的表达式
    172                 exp = replace_symbol(exp)   # 检查计算后的表达式是否存在类似 '+- '等字符,存在的话先替换,后执行
    173                 return add_sub(exp)
    174             else:
    175                 pass
    176         else:
    177             pass
    178     else:
    179         return exp  # 不匹配到,返回exp
    180 
    181 def calculate(exp):
    182     '''
    183     获取一个运算表达式,返回运算结果
    184     :param exp: 表达式
    185     :return: 运算结果
    186     '''
    187     result = power(exp)         # 执行幂运算,返回运算结果
    188     result = mul_div(result)    # 执行乘法、除法、取余、取整运算,返回运算结果
    189     result = add_sub(result)    # 执行加法、减法运算,返回运算结果
    190     return result
    191 
    192 if __name__ == '__main__':
    193     print(u'33[31;1m欢迎使用计算器33[0m'.center(100,'='))
    194     while True:
    195         # 计算 s = '1-2 *(   (60- 30+(-40.0/5)*(9-2*5 / 3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
    196         get_input = raw_input(u'
    33[32;1m请输入一个表达式 | 退出(q): 33[0m').strip()
    197         get_input = ''.join(re.split('s+', get_input))    # 除去输入表达式中多余的空格
    198         if get_input == '':     # 空字符,重新输入
    199             continue
    200         elif get_input == 'q':
    201             print(u'33[31;1m退出程序!33[0m')
    202             break
    203         elif check_exp(get_input):    # 输入的表达式合法
    204             exp = replace_symbol(get_input)     # 化简输入的表达式
    205             print(u'化简后的表达式:33[33;1m%s33[0m
    ' % exp)
    206             parenthesis(exp)
    207         else:
    208             pass
    计算器_python27
  • 相关阅读:
    GC原理---垃圾收集算法
    GC原理---对象可达判断
    散列算法和哈希表结构
    桶排序
    Spring事务梳理
    AQS
    重入锁
    CAS
    研究一下phpspider
    用php写爬虫去爬数据
  • 原文地址:https://www.cnblogs.com/suke99/p/5197423.html
Copyright © 2011-2022 走看看