利用正则制作计算器
核心思想: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 i 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
a = input ( '计算式:' ).strip()
# 去除空格处理,得到1-2*((60-30+(-40/5)*20)-(-4*3)/(16-3*2))
a = 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 i in lst]))
return res # 返回一个计算完毕的字符串数据类型的 数字
def remove_bracket(s):
s = s.replace( ' ' , '') # 去掉空格
while True :
ret = re.search(r '\([^()]+\)' , s) # 匹配最内层的括号
if ret: # 能匹配到括号 就先处理括号内的加减乘除
no_bracket_exp = ret.group() # 拿到括号中的表达式
ret = dealwith(no_bracket_exp) # 把括号中的表达式交给的dealwith
s = s.replace(no_bracket_exp, ret, 1 )
else : # 不能匹配到括号 就字节处理加减乘除
ret = dealwith(s) # 把表达式交给的dealwith
return ret
s = '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 |
a = '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 i 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 )
s = proce_symbol(famu)
return bras(s)
else :
s = proce_symbol(famu)
ret = total(s)
return ret
print (bras(new_a))
|