问题一
str1 = re.sub("([^()])", result, str1),替换的时候会把当前到下一个)全部替换。
查看结果是因为默认多次替换原因导致str1 = re.sub("\(*[^()]*\)", result, str1, count=1)
替换一次正常
问题二:
怎么精确的寻到一个-+,++,*+,/+等等的双重符号。。。像下面这样每句替换吗?
str1 = re.sub("++", "+",str1)
str1 = re.sub("-+", "-",str1)
str1 = re.sub("*+", "*",str1)
str1 = re.sub("/+", "/",str1)
NO,正则就是一个找规律的游戏,上面的句子完全可以一句替代:
str1 = re.sub('\W+', re.search('\W-', str1).group()[0], str1,count=1)
但是,上面有个问题遇到(3-2)+1,会把)+也给找出来,太不智能了,怎么办?
试试下面的:
str1 = re.sub('[*+/-]+', re.search('[*+/-]-', str1).group()[0], str1,count=1)
只认这四个,完美解决了)+的问题,oh yeah~
问题三:
运行整数时,程序正常,运行浮点,程序就出问题,因为多了.这个非数字字符。
问题四:
测试完美的程序,运算作业题时报错。
测试打印-->2> 1-2*((60-30-1388360.0.88095238098+1.2.0
报错:
subtotal += float(i)
ValueError: could not convert string to float: '-2*'
分析:为什么会出现乱码呢?
测试-(-5/3(8-10)+23)+33这样公式都可以,比较一下,发现了问题
题目的式子,是两个括号在一起的。。。。。。
1 - 2 ( (60-30 +(-40/5) (9-25/3 + 7 /399/42998 +10 568/14 )) - (-43)/ (16-32) )
改进后的正则:就算你有10个括号在一起,也不怕!r"\([^\(+][\d+\W+][^\(\)]*[\W+\d+][^\)+]\)"
附代码:
#!--coding:utf-8--
import re
def parenthesis(str1) 获取最内层括号内的表达式,并用result函数的结果替换回表达式,循环去括号
def result(str1, i=0) 返回的是计算结果,str1是一个没有括号的表达式!
初始作业表达式
string = '1 - 2 ( (60-30 +(-40/5) (9-25/3 + 7 /399/42998 +10 568/14 )) - (-43)/ (16-32) )'
def result(str1, i=0):
计算没有括号的表达式结果,先算*/,再算加减。
while i < 2: # 两次,因为防止去完*- 和/-以后再次出现--/+-
i += 1
str1 = re.sub("--", "+", str1) # 去括号的第一步,防止-(-1)出现,做替换
str1 = re.sub("\+-", "-", str1) # 去括号的第二步,防止+(-1)出现,做替换
# print('str11-->%d>'%i, str1)
# 去掉多余的加号。
while re.search('[\*\+/-]\+', str1):
str1 = re.sub('[\*\+/-]\+', re.search('[\*\+/-]\+', str1).group()[0], str1, count=1)
# 开始[*/][-]运算
opt = re.search('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*', str1) # 查找提取*/号和前后的数字,并作为循环条件
while opt:
opt = opt.group() # 提取字符串
if re.search('[\*/]-', opt): # 判断减号
sub_str = re.sub('[\*/]-', re.search('[\*/]', opt).group(), opt, count=1) # 去掉减号
symbol = '-'
else: # 没有减号,不做处理
symbol = ''
sub_str = opt
arithmetic = re.search('[\*/]', sub_str).group() # 提取运算符
num_list = re.search('(\d*[\.\d]\d*)[\*/](\d*[\.\d]\d*)', sub_str).groups() # 提取运算符前后的数字
# 用运算结果,替换掉str1中对应的字符,重新赋值给str1
str1 = re.sub('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*',
symbol+str(eval(str(num_list[0]+arithmetic+num_list[1]))), str1, count=1)
opt = re.search('\d*[\.\d]\d*[\*/][\-]*\d*[\.\d]\d*', str1) # 查找提取*/号和前后的数字,并作为循环条件
# 上面程序处理后,成为一个只有+-的字符串,下面处理+和-
if str1[0].isdigit(): # 首位是数字,添加+号,为正则准备。
str1 = '+' + str1
subtotal = 0 # 初始化和值
opt = re.findall('(\W\d*[\.\d*]\d*)', str1) # 带加减和数字的分组
for i in opt: # 累加
subtotal += float(i)
return str(subtotal) # 返回计算结果
def parenthesis(str1):
str1 = re.sub(r'\s+', '', str1)
search = re.search(r"([^(+][\d+\W+][^()][\W+\d+][^)+])", str1) # 搜索最内层括号,并作为循环条件
while search:
str_sub = search.group()
temp = str_sub[1:-1] # 去掉括号
result_str = result(temp) # 调用算术运算函数
str1 = re.sub(r"([^(+][\d+\W+][^()][\W+\d+][^)+])", result_str, str1, count=1) # 括号内计算结果替换回去
search = re.search(r"([^(+][\d+\W+][^()]*[\W+\d+][^)+])", str1) # 搜索最内层括号
return str1
def error(str1):
try:
eval(str1)
except:
print('表达式错误!')
return True
程序开始
while True:
expression = input('[Q]退出,请输入算术表达式,例如:\n%s\n-->>' % string).strip()
if expression.lower() == 'q':
print('退出!')
break
print('您输入的表达式是:', expression)
if error(expression):
continue
else:
print('正则-运算结果是:', result(parenthesis(expression)))
print('EVAL-运算结果是:', eval(expression))
input('按任意键继续...')
转载于:https://blog.51cto.com/yishi/2048887