zoukankan      html  css  js  c++  java
  • Python之实现一个简易计算器 用re

    功能分析

      用户输入一个类似这样 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )  这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号,然后自己动手写代码解析其中的表达式,实现加减乘除最后得出的结果与真实的计算机所算的结果必须一致。

    程序实现流程分析

    从最简单的开始。

    1、按运算符的优先级别,先编写一个程序实现对字符串的乘除处理

    2、再编写一个程序实现对字符串的加减处理

    3、编写一个程序实现对括号内容匹配处理

    4、编写对原始字符串数据的处理,甄别。是否输入错误等。。。。

     实现:

    1、先实现乘除功能:

    # -*- coding:utf-8 -*-
    import re
    '''
    Created on 2018年7月10日
    
    @author: Administrator
    '''
    #第一步,实现一个公式的乘除 #9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 假设没有空格在里面
    
    sub_s='9-10.0/3 + 7/3*99/4*2998 +10*568/14 '
    print(sub_s)
    
    #先计算乘除
    def chengchu(gongshi):
        new_s_s=gongshi
        if '*' in new_s_s or '/' in new_s_s:#先计算乘除
            sub_sub_s=re.search('(d*.?d*)([*/])(d*.?d*)',new_s_s)
            if sub_sub_s==None:
                pass
            else:
                # print(sub_sub_s)
                # print(sub_sub_s.span())
                # print(sub_sub_s.group())
                if sub_sub_s.group(2)=='*':
                    sss=str(float(sub_sub_s.group(1))*float(sub_sub_s.group(3)))
                    # print(sss)
                elif sub_sub_s.group(2)=='/':
                    sss = str(float(sub_sub_s.group(1)) / float(sub_sub_s.group(3)))
                    # print(sss)
                else:
                    print('没有需要运算的乘除法。')
            # s_new=s[0:18]+'-8'+s[25:]
            #     gongshi[0:sub_sub_s.span()[0]] + sss + gongshi[sub_sub_s.span()[1]:]
                new_s_s=gongshi[0:sub_sub_s.span()[0]]+sss+gongshi[sub_sub_s.span()[1]:]
                # print(new_s_s)
                return chengchu(new_s_s)
        else:
            return new_s_s
        # if '+' in gongshi or '-' in gongshi:  # 再计算加减
    
    #再计算加减
    def jiajian():
        pass
    
    print(chengchu(sub_s))

    运行结果:

    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/7.5/计算器.py
    9-10.0/3 + 7/3*99/4*2998 +10*568/14 
    9-3.3333333333333335 + 173134.50000000003 +405.7142857142857 
    
    Process finished with exit code 0

    2、实现加减功能:

     1 #再计算加减 sub_s_s=9-3.3333333333333335 + 173134.50000000003 +405.7142857142857
     2 sub_s_s='9-3.3333333333333335+173134.50000000003+405.7142857142857' #假设没有空格
     3 print(sub_s_s)
     4 def jiajian(gongshi_jiajian):
     5     new_s_s = gongshi_jiajian
     6     if '+' in new_s_s or '-' in new_s_s:#计算加减
     7         sub_sub_s=re.search('(d*.?d*)([+-])(d*.?d*)',new_s_s)
     8         if sub_sub_s==None:
     9             pass
    10         else:
    11             if sub_sub_s.group(2) == '+':
    12                 sss=str(float(sub_sub_s.group(1))+float(sub_sub_s.group(3)))
    13                 # print(sss)
    14             elif sub_sub_s.group(2)=='-':
    15                 sss = str(float(sub_sub_s.group(1)) - float(sub_sub_s.group(3)))
    16                 # print(sss)
    17             else:
    18                 print('没有需要运算的加减法。')
    19         new_s_s = sss + gongshi_jiajian[sub_sub_s.span()[1]:]
    20         # print(new_s_s)
    21         return jiajian(new_s_s)
    22     else:
    23         return new_s_s
    24 
    25 print(jiajian(sub_s_s))

    运行结果:

    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/7.5/计算器.py
    9-3.3333333333333335+173134.50000000003+405.7142857142857
    173545.88095238098
    
    Process finished with exit code 0

    3、实现匹配出最里层的括号内容

     1 # -*- coding:utf-8 -*-
     2 import re
     3 '''
     4 Created on 2018年7月9日
     5 
     6 @author: Administrator
     7 '''
     8 #用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)
     9 # 这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号
    10 s='1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
    11 s1='1 - 2 * ( (60-30* (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
    12 def kuohao(gongshi_kuohao):#输入带括号的公式
    13     str_kuohao=gongshi_kuohao
    14     if '(' in str_kuohao and ')' in str_kuohao:
    15         guize_kuohao = re.compile('(()([^()]*)())')  # 匹配出最里层的括号的规则
    16         print(guize_kuohao.search(str_kuohao))
    17         print(guize_kuohao.search(str_kuohao).group())
    18         print(guize_kuohao.search(str_kuohao).group(1))
    19         print(guize_kuohao.search(str_kuohao).group(2))#取到最里层括号里面的字符串
    20         print(guize_kuohao.search(str_kuohao).group(3))
    21 
    22 print(kuohao(s))
    23 print(kuohao(s1))

    运行结果:

    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/7.5/计算器.py
    <_sre.SRE_Match object; span=(18, 25), match='(-40/5)'>
    (-40/5)
    (
    -40/5
    )
    None
    <_sre.SRE_Match object; span=(18, 58), match='(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )'>
    (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )
    (
    9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 
    )
    None
    
    Process finished with exit code 0

    4、实现原始字符串错误检测,处理功能

     1 # -*- coding:utf-8 -*-
     2 import re
     3 '''
     4 Created on 2018年7月9日
     5 
     6 @author: Administrator
     7 '''
     8 #用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)
     9 # 这样的表达式,假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号
    10 s='1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ))   - (-4*3)/ (16-3*2))'
    11 def qingxi(gongshi_qingxi):##对原始公式进行清洗、
    12     str_qingxi_kongge=re.sub('s','',gongshi_qingxi)#去掉所有空格
    13     # print(str_qingxi_kongge)
    14     #统计括号
    15     str_qingxi_kuohao=re.findall('[()]',str_qingxi_kongge)
    16     # print(str_qingxi_kuohao)
    17     if str_qingxi_kuohao.count('(')==str_qingxi_kuohao.count(')'):#左括号和右括号相等
    18         for i in range(1,int(len(str_qingxi_kuohao))):#判断左侧的左括号,要一直大于等于左侧的右括号
    19             # print(i)
    20             if str_qingxi_kuohao[0:i].count('(') >= str_qingxi_kuohao[0:i].count(')'):
    21                 continue
    22             else:
    23                 print('公式中括号出现错误,请检查第 %d 括号问题'%i)
    24     else:
    25         print('公式中括号出现错误,括号不是成对出现。')
    26     # if re.search('([^d])',str_qingxi_kongge):
    27     #     print('公式中括号出现错误,出现空括号')
    28 
    29     return str_qingxi_kongge
    30 
    31 print(qingxi(s))

    结果:

    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/7.5/计算器.py
    1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
    
    Process finished with exit code 0

    最终结果:(对于之前写的代码,存在逻辑上漏洞,也在下面代码中改善)

      1 # -*- coding:utf-8 -*-
      2 import re
      3 
      4 ###############################################清洗,格式化字符串#########################################################################
      5 def qingxi(string):##对原始公式进行清洗、
      6     flag=True
      7     string=string.replace(' ','')#去掉所有空格
      8     string = string.replace('+-', '-')
      9     string = string.replace('--', '+')
     10     string = string.replace('++', '+')
     11     string = string.replace('-+', '-')
     12     string = string.replace('*+', '*')#假设,只有加减乘除运算。输入时可能出现,但是运算中不可能遇到这种情况
     13     string = string.replace('/+', '/') #假设,只有加减乘除运算。输入时可能出现,但是运算中不可能遇到这种情况
     14     #防止出现 类似 2*-3==(-1)*2*3
     15     s_str=re.search('(d+.?d**)(-)', string)
     16     if s_str :
     17         s_str=s_str.group(1)#拿到-前面的数字 2*
     18         string = re.sub('d+.?d**-', '-'+s_str, string)  # 防止出现 类似 2*-3==-2*3
     19     s_str_sub = re.search('(d+.?d*/)(-)', string)
     20     if s_str_sub:
     21         s_str = s_str_sub.group(1)  # 拿到-前面的数字 2*
     22         string = re.sub('d+.?d*/-', '-' + s_str, string)  # 防止出现 类似 2/-3==-2/3
     23 
     24     # 遇到+- 或是-+ 统统换成- 运算符
     25     str_qingxi=re.findall('[()]',string)
     26     if re.findall('[a-z]+',string.lower()):
     27         print('存在非法字符',re.findall('[a-z]+',string.lower()))
     28         flag=False
     29     elif str_qingxi.count('(')==str_qingxi.count(')'):#左括号和右括号相等 ()必须成对出现
     30         for i in range(1,int(len(str_qingxi))):#判断左侧的左括号,要一直大于等于左侧的右括号,防止出现类似  ))((  的情况
     31             if str_qingxi[0:i].count('(') >= str_qingxi[0:i].count(')'):
     32                 continue
     33             else:
     34                 print('公式中括号出现错误,请检查第 %d 处括号问题'%i)
     35                 flag=False
     36     else:
     37         print('公式中括号出现错误,存在括号没有闭合。')
     38     if flag:
     39         return string
     40 ###############################################乘除计算#########################################################################
     41 def chengchu(string):
     42 
     43 
     44     if '*' in string or '/' in string:#先计算乘除
     45         s_string = re.search('(d+.?d*)([*/])(d+.?d*)', string)
     46         s_s_string=s_string.group()#
     47     # s_string = re.search('(d+.?d*)([*/])(d+.?d*)', string)
     48     # s_s_string = s_string.group()
     49     # if s_string:
     50 
     51         if s_string.group(2)=='*':
     52             sss=str(float(s_string.group(1))*float(s_string.group(3)))
     53             # print(sss)
     54             new_string = string.replace(s_s_string, sss)
     55             return chengchu(new_string)
     56         elif s_string.group(2)=='/':
     57             sss = str(float(s_string.group(1)) / float(s_string.group(3)))
     58             # print(sss)
     59             new_string = string.replace(s_s_string, sss)
     60             return chengchu(new_string) #递归。。。
     61     else:
     62         # print('没有需要运算的乘除法。')
     63         return string
     64 
     65 ###############################################加减计算#########################################################################
     66 def jiajian(string):
     67     s_string = re.search('(d+.?d*)([+-])(d+.?d*)', string)
     68     if s_string:#条件成立,表示匹配到加法,或是加法公式。如果匹配'-5',则条件不成立,没有返回值
     69         s_s_string=s_string.group()
     70         if s_string.group(2) == '+':
     71             sss=str(float(s_string.group(1))+float(s_string.group(3)))
     72             new_string=string.replace(s_s_string,sss)
     73             return jiajian(new_string)
     74         elif s_string.group(2)=='-':
     75             sss =str(float(s_string.group(1)) - float(s_string.group(3)))
     76             new_string=string.replace(s_s_string,sss)
     77             return jiajian(new_string)
     78     else:
     79         # print('没有需要运算的加减法。')
     80         return string
     81 ###############################################组合计算#########################################################################
     82 def jisuanqi(string):#计算器函数
     83 
     84     while re.search('(',string):#有括号
     85         string = qingxi(string)#每对最里层的括号运算一次,清洗一下,防止出现'--5',‘+-8’ 等情况
     86         strs=re.search('([^()]+)',string).group()#检测最里层的括号
     87         # strs_s_s=strs.group()
     88         strs_s=chengchu(strs)#
     89         strs_s=qingxi(strs_s)
     90         strs_s=jiajian(strs_s).strip('()')#
     91         string=string.replace(strs,strs_s)
     92 
     93     else:#无括号
     94         string = qingxi(string)#每对最里层的括号运算一次,清洗一下,防止出现'--5',‘+-8’ 等情况
     95         strs = chengchu(string)
     96         strs=qingxi(strs)
     97         strs = jiajian(strs)
     98         return  strs#
     99 
    100 
    101 
    102 sour='1 + 2 * ((60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ))   +- (-4*3)/ (16-3*2))'
    103 s1=jisuanqi(sour)
    104 print(s1)

     运行结果:

    "D:Program Files (x86)python36python.exe" F:/python从入门到放弃/计算器3.py
    -2776675.4952380955
    
    Process finished with exit code 0
  • 相关阅读:
    HDU Problem 1811 Rank of Tetris【拓扑排序+并查集】
    POJ Problem 2367 Genealogical tree【拓扑排序】
    HDU Problem 2647 Reward【拓扑排序】
    HDU Problem 1285 确定比赛名次【拓扑排序】
    HDU Problem HDU Today 【最短路】
    HDU Problem 3665 Seaside【最短路】
    HDU Problem 一个人的旅行 【最短路dijkstra】
    HDU Problem 1596 find the safest road【最短路dijkstra】
    Beyond Compare文本合并进行内容替换要注意什么
    用这些工具都可以比较代码的差异
  • 原文地址:https://www.cnblogs.com/Mengchangxin/p/9284337.html
Copyright © 2011-2022 走看看