s22day8
使用正则编写计算公式功能
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
#num='1-2*((60-30+(-40/5)*(9+7+10))-(-4*3)/(16-3*2))'
def chengchu (num):
#使用正则表达式分割*/
num=num.strip()
num = num.replace('++','+')
num = num.replace('--','+')
num = num.replace('+-','-')
num = num.replace('-+','-')
s1=re.search('-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?', num)
# print(s1)
# 乘除号不存在,返回输入的表达式
if not s1:
return num
renum=re.search('-?\d+(\.\d+)?[*/]-?\d+(\.\d+)?', num).group()
# print(renum)
#如果*分割后长度大于1进入计算
if len(renum.split('*')) > 1 and len(renum.split('-'))>1:
n1,n2=renum.split('*')
va=-float(n1)*-float(n2)
va = "%.1000f" % va
#如果*分割后长度大于1且以-号开头进入负数乘法运算
# print(va)
elif len(renum.split('*')) >1:
n1, n2 = renum.split('*')
# print(n1,n2)
va = float(n1) * float(n2)
va = "%.1000f" % va
#如果/分割后长度大于1且以-号开头进入负数除法运算
elif len(renum.split('/')) >1 and len(renum.split('-'))>1:
n1, n2 = renum.split('/')
# print(n1,n2)
# 计算负数的减法
va = -float(n1) / -float(n2)
va= "%.1000f" %va
else:
#如果/分割后长度大于1进入计算
n1,n2=renum.split('/')
va=float(n1)/float(n2)
va = "%.1000f" % va
# va=round(va,7)
#使用替换产生新公式
# print(num)
vv = '+'+str(va) if float(va)>0 else str(va)
next_num=num.replace(renum,vv,1)
# print('旧公式:' + renum)
# print( '新公式:' + next_num)
# print(next_num)
#使用递归重新进入方法进行下一步计算
# print(next_num)
return chengchu(next_num)
def jiajian(num):
num = num.strip()
#将公式中的++,--,+-,-+,替换
num = num.replace('++','+')
num = num.replace('--','+')
num = num.replace('+-','-')
num = num.replace('-+','-')
s1=re.search('-?\d+(\.\d+)?[+-]-?\d+(\.\d+)?', num)
# print(s1)
# 乘除号不存在,返回输入的表达式
if not s1:
return num
#已+-进行分割
renum=re.search('-?\d+(\.\d+)?[+-]-?\d+(\.\d+)?', num).group()
# print(renum)
#判断以+号分割后的长度,如果大于1进入计算
if len(renum.split('+')) > 1:
n1, n2 = renum.split('+')
#计算+法
va = float(n1) + float(n2)
va = "%.1000f" % va
#如果是以-开头需要单独计算
elif renum.startswith('-'):
n1, n2,n3 = renum.split('-')
# print(n2,n3)
# 计算负数的减法
va = -float(n2) - float(n3)
va = "%.1000f" % va
else:
#计算-法
n1, n2 = renum.split('-')
va = float(n1) - float(n2)
va = "%.1000f" % va
# va=round(va,7)
#使用字符串替换生成新公式
next_num=num.replace(renum,str(va),1)
# print('旧公式:' + renum)
# print( '新公式:' + next_num)
#使用递归重新进入方法进行下一步计算
return jiajian(next_num)
def kouhao(num):
num = num.strip()
# 判断公式是否存在小括号,如果不存在小括号,直接调用乘除,加减方法
if not re.search('\(([^()]+)\)', num):
va1 = chengchu(num)
va2 = jiajian(va1)
return va2
# 如果公式存在小括号,匹配出优先级最高的小括号
renum=re.search(r'\(([^()]+)\)', num).group()
# print(renum)
#将正则匹配完成的小括号去除
qnum=renum.strip('[\(\)]')
# print(qnum)
#进行先乘除后加减的运算
v1=chengchu(qnum)
# print(v1)
v2=jiajian(v1)
# print(v2)
#使用字符串替换生成新公式
next_num=num.replace(renum,str(v2),1)
#使用递归重新进入方法进行下一步计算
return kouhao(next_num)
w = '\033[33;1m公式计算系统\033[0m'
print(w.center(50, '*'), '\n')
while True :
try:
num = input('\033[33;1m请输入你要计算的公式[q:退出]:\033[0m').strip()
if num == 'q': # 退出计算
break
elif len(num) == 0:
print('\033[0;31m公式为空,请重新输入!\033[0m')
continue
else:
#去除空格
num=num.replace(' ','')
# 用eval对计算结果进行验证
enum = eval(num)
# 用正则计算的结果
znum = kouhao(num)
enum = float(enum)
znum = float(znum)
# 判断两种计算结果,如果相等,则计算正确,输出结果
if enum == znum:
print('计算结果正常!')
print('eval计算结果:%s' % enum)
print('func计算结果:%s' % znum)
# 如果计算结果不等,提示异常,并返回两种方式的计算结果
else:
print('\033[0;31m计算结果异常,请重新检查!\033[0m')
print('\033[0;31meval计算结果:%s\033[0m' % enum)
print('\033[0;31mfunc计算结果:%s\033[0m' % znum)
except:
print('\033[0;31m输入表达式不合法,请重新检查!\033[0m')
#测试公式:
#((984-618*7/23+22/831/3487+4+3546.76*721595+69)+(971/93+6-7-5395-9.44+636/5+287*7341*3/6927-99))-(994+4+49*6958*8+5323339)
#1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
#-1+3*(-3*2-2/-2+1)/2
#((98*6+9346779/2/5+613-57-1813/9-59)*(9555*6*148*9/3+64.94955*3-7/34115+6.9))/(91-86-9519)
#((967+875965446+82-37/69/1+7963362/6299)-(95-8*739*13927+536587/39))*(9968+3721-3*69669166119318178*9)