利用正则制作计算器

核心思想:1.先考虑没有括号的式子如何进行运算,然后考虑正则匹配有括号的式子,通过逐步替换

利用正则计算:1 - 2 * ( (60-30 +(-40/5) * 20) - (-4*3)/ (16-3*2) )

# 方案1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python    # -*- coding:utf-8 -*-
# author: Learning       time:2018/4/30
 
import  re
# 定义一个乘除运算函数,最终返回一个运算结果
def  mul_div(cal):
     if  '*'  in  cal:
         x, y  =  cal.split( '*' )
         return  float (x)  *  float (y)
     if  '/'  in  cal:
         x, y  =  cal.split( '/' )
         return  float (x)  /  float (y)
     
# 定义一个处理加减符号的函数,这步是由于乘除运算完可能为负导致的
def  proce_symbol(cal):
     cal  =  cal.replace( '++' , '+' )
     cal  =  cal.replace( '+-' '-' )
     cal  =  cal.replace( '--' '+' )
     cal  =  cal.replace( '-+' '-' )
     return  cal
 
# 定义一个对内层没有括号的公式进行运算的函数,最终返回一个结果
def  inner(content):
     """
     这步对内层的乘除进行循环处理,直到里面没有了乘除运算,全部替换成了结果
     :param content:
     :type content:
     :return: 一个不带括号的运算式的结果
     :rtype:
     """
     # 浮点型匹配整数和浮点数啊哥,不是整数匹配浮点数
     # 最后变成这样1-2*-128.8,要注意这里的正则匹配
     con  =  re.search(r '\d+\.?\d*[*/]\-?\d+\.?\d*' , content)
     while  con:   # 如果当中有乘除号
         con  =  con.group()
         temp  =  mul_div(con)   # 得到结果
         content  =  content.replace(con, str (temp))   # 对内层运算式进行替换
         content  =  proce_symbol(content)
         #替换计算式中的乘除运算,直到替换完,对于冲突的+-号也进行替换
         return  inner(content)    # 通过循环一直运算式中的乘除运算计算完
     else :    # 如果没有乘除号
         # 对加减进行运算处理,把他们整到列表里面,挨个进行处理计算
         lis  =  re.findall(r '[+-]?\d+\.?\d*' , content)
         if  len (lis)> 0 :
             total_num  =  0
             for  in  lis:
                 total_num  + =  float (i)
             return  total_num
         else :
             return  lis[ 0 ]
 
# 匹配最内层的括号
def  pars(cal):
     """
     定义一个计算最内层运算的函数
     :param cal:
     :type cal:
     :return:最能层运算
     :rtype:
     """
     par  =  re.search( '\(([^()]*)\)' , cal)
     while  par:    # 如果当中有括号
         content  =  par.group()    # (-40/5)
         temp  =  inner(content.strip( '()' ))   # 去括号,并处理结果-8
         cal  =  cal.replace(content, str (temp))
         return  pars(cal)
     # 判断里面的运算符,可以有加减乘除
     else :
         ret  =  inner(cal)  # 如果没有括号
         return  ret
 
=  input ( '计算式:' ).strip()
# 去除空格处理,得到1-2*((60-30+(-40/5)*20)-(-4*3)/(16-3*2))
=  re.sub( '\s' ,'', a)
print (pars(a))

 方案2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import  re
def  cal(exp):
     if  '*'  in  exp:
         a,b  =  exp.split( '*' )
         return  str ( float (a)  *  float (b))
     elif  '/'  in  exp:
         a, b  =  exp.split( '/' )
         return  str ( float (a)  /  float (b))
 
def  format (exp):
     exp  =  exp.replace( '++' , "+" )
     exp  =  exp.replace( '-+' , "-" )
     exp  =  exp.replace( '+-' , "-" )
     exp  =  exp.replace( '--' , "+" )
     return  exp
 
def  dealwith(no_bracket_exp):
     # 匹配乘除法
     while  True :
         mul_div  =  re.search( '\d+(\.?\d+)?[*/]-?\d+(\.?\d+)?' , no_bracket_exp)
         if  mul_div:
             exp  =  mul_div.group()
             result  =  cal(exp)
             no_bracket_exp  =  no_bracket_exp.replace(exp, result,  1 )   # (-8)
         else : break
     no_bracket_exp  =  format (no_bracket_exp)
     # 计算加减法
     lst  =  re.findall(r '[-+]?\d+(?:\.\d+)?' , no_bracket_exp)
     res  =  str ( sum ([ float (i)  for  in  lst]))
     return  res    # 返回一个计算完毕的字符串数据类型的 数字
 
def  remove_bracket(s):
     =  s.replace( ' ' , '')      # 去掉空格
     while  True :
         ret  =  re.search(r '\([^()]+\)' , s)    # 匹配最内层的括号
         if  ret:       # 能匹配到括号 就先处理括号内的加减乘除
             no_bracket_exp  =  ret.group()     # 拿到括号中的表达式
             ret  =  dealwith(no_bracket_exp)   # 把括号中的表达式交给的dealwith
             =  s.replace(no_bracket_exp, ret,  1 )
         else :        # 不能匹配到括号 就字节处理加减乘除
             ret  =  dealwith(s)   # 把表达式交给的dealwith
             return  ret
 
=  '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
print (remove_bracket(s))

 和方案二一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
=  '1 - 2 * ( (60-30 +(-40/5) * 20) - (-4*3)/ (16-3*2) )'
import  re
new_a  =  re.sub( ' ' ,'',a)   # 去括号处理
def  proce_symbol(cal):   # 去重复加减号
     if  '++'  in  cal:cal  =  cal.replace( '++' , '+' )
     if  '+-'  in  cal:cal  =  cal.replace( '+-' '-' )
     if  '--'  in  cal:cal  =  cal.replace( '--' '+' )
     if  '-+'  in  cal:cal  =  cal.replace( '-+' '-' )
     return  cal
def  mul_div(famula):
     if  '*'  in  famula:
         num1, num2  =  famula.split( '*' )
         total  =  str ( float (num1)  *  float (num2))
         return  total
     if  '/'  in  famula:
         num1, num2  =  famula.split( '/' )
         total  =  str ( float (num1)  /  float (num2))
         return  total
def  total(famula):
     while  True :
         if  '*'  or  '/'  in  famula:
             num  =  re.search(r '\d+(\.?\d+)?[*/]\-?\d+(\.?\d+)?' ,famula)
             if  num:
                 num  =  num.group()
                 nums  =  mul_div(num)
                 famula  =  famula.replace(num, nums,  1 )
                 famula  =  proce_symbol(famula)
            # 如果算式中剩下加减运算
             else :
                 lis  =  re.findall(r '[-]?\d+(?:\.?\d+)?' ,famula)
                 sums  =  sum ([ float (i)  for  in  lis])
                 return  sums
def  bras(famu):
     while  True :
         bra  =  re.search( '\([^()]+\)' ,famu)   # 获取括号内的内容
         if  bra:
             bra  =  bra.group()
             ret  =  total(bra)
             famu  =  famu.replace(bra, str (ret), 1 )
             =  proce_symbol(famu)
             return  bras(s)
         else :
             =  proce_symbol(famu)
             ret  =  total(s)
             return  ret
print (bras(new_a))
  

转载于:https://www.cnblogs.com/mmqqhh/p/10904963.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值