1.极限压缩版

import re, functools
def cal(formula):
while re.search('(?:\d+\.?\d+|\d+)[+\-*/]', formula):
while re.search('[*/]', formula): formula = re.sub('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', str(functools.reduce(lambda i, j: float(i) * float(j), re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group().split('*')) if '*' in re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group() else functools.reduce(lambda i, j: float(i) / float(j), re.search('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)', formula).group().split('/'))), formula, 1)
if re.search('(?:\d+\.?\d+|\d+)[+\-]', formula): formula = re.sub('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', str(functools.reduce(lambda i, j: float(i) + float(j), re.search('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group().rsplit('+', 1)) if '+' in re.search('(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group() else functools.reduce(lambda i, j: float(i) - float(j), re.search('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)', formula).group().rsplit('-', 1))), formula, 1)
return formula
formula = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
while re.search('\([^\(\)]+\)', formula):
formula = re.sub('\([^\(\)]+\)', cal(re.search('\([^\(\)]+\)', re.sub('\s', '', formula)).group()).strip('()'), formula, 1)
while re.search('[+\-*/]-', formula): formula = re.sub('[+]-', '-', formula) if '+-' in formula else re.sub('--', '', formula) if formula.startswith('--') else re.sub('(?:\d+\.?\d+|\d+)[*/]-', '-' + re.findall('(?:\d+\.?\d+|\d+)[*/](?=-)', formula)[0], formula) if re.search('[*/]-', formula) else re.sub('--', '+', formula)
print(cal(formula).split('.0')[0] if cal(formula).endswith('.0') else cal(formula))

2.完整版

import re
from functools import reduce def plus_minus(formula):
'''
计算无括号的加减法算式
:param formula: 等待计算的只包含加减法的字符串
:return: 计算结果的字符串
'''
p1 = re.compile('-?(?:\d+\.?\d+|\d+)[+\-](?:\d+\.?\d+|\d+)') # 匹配一次加减法
while re.search(p1, formula): # 每次计算一个二元加减,并替换到原字符串上,直到计算并计算完所有数
x = re.search(p1, formula).group() # 匹配出一次计算,判断是加法还是减法,再由reduce把分割后的两个数交给匿名函数去计算。
formula = re.sub(p1, str(reduce(lambda i, j: float(i) + float(j), x.rsplit('+', 1)) if '+' in x else reduce(lambda i, j: float(i) - float(j), x.rsplit('-', 1))), formula, 1)
return formula
# ps.计算加减法可以采用与乘除法不同的方式,可以把所有数全匹配出来再一起计算出来 def multi_divi(formula):
'''
计算无括号的乘除法算式
:param formula: 等待计算的只包含乘除法的字符串
:return: 计算结果的字符串
'''
p = re.compile('(?:\d+\.?\d+|\d+)[*/](?:\d+\.?\d+|\d+)')
while re.search(p, formula):
y = re.search(p, formula).group()
formula = re.sub(p, str(reduce(lambda i, j: float(i) * float(j), y.split('*')) if '*' in y else reduce(lambda i, j: float(i) / float(j), y.split('/'))), formula, 1)
return formula def parentheses_parse(formula):
'''
用来处理括号,并调用加减乘除完成计算
:param formula: 数学算式的字符串,支持加减乘除和括号
:return: 最终结果的整型或浮点型
'''
formula = re.sub('\s', '', formula)
p = re.compile('\([^\(\)]+\)') # 匹配内层括号
while re.search(p, formula): # 循环到没有括号为止
f = re.search(p, formula).group()
formula = re.sub(p, plus_minus(multi_divi(f)).strip('()'), formula, 1) # 调用加减法嵌套乘除法,计算完括号内的式子,并去除括号 # 处理去除括号后可能出现的其他符号与负号相连的情况
while re.search('[+\-*/]-', formula):
formula = re.sub('[+]-', '-', formula)
formula = re.sub('--', '', formula) if formula.startswith('--') else re.sub('--', '+', formula) # 正负为负,负负为正,并且避免正号出现在最前端
if re.search('[*/]-', formula): # 遇到乘除连接负号的情况时,需要先把负号前置,再进行一次上面加减连接负号的处理
n = re.search('(?:\d+\.?\d+|\d+)[*/](?=-)', formula).group() # 这里使用正向预匹配获得如'7*-'这样的序列中的'7*'的部分
formula = re.sub('(?:\d+\.?\d+|\d+)[*/]-', '-' + n, formula) # 使用刚获得的字符串进行替换,来使‘7*-’变成‘-7*’的样子
formula = plus_minus(multi_divi(formula)) # 没有括号了,再计算最后一次
if formula.endswith('.0'): # 优化显示
formula = int(formula.split('.0')[0])
else:
formula = float(formula)
return formula # 在此处输入算式
print(parentheses_parse('1-2*((60- 30+(-40/5)*(9 -2*5/3+7/3*99/4*2998+1 0*568/14))-(-4*3)/(16-3*2))'))

3.思路清晰版

import re
from functools import reduce def mul_div(exp):
"""
计算两个数的乘法或者除法
:param exp:
:return:
"""
if '*' in exp:
a, b = exp.split('*')
return float(a)*float(b)
if '/' in exp:
a, b = exp.split('/')
return float(a) / float(b) def exp_fmt(exp):
"""
符号整理
:param exp:
:return:
"""
while re.search('[+-]{2,}',exp):
exp = exp.replace('--','+')
exp = exp.replace('+-','-')
exp = exp.replace('-+','-')
exp = exp.replace('++','+')
return exp def remove_addsub(exp):
"""
计算两个数的加减法
:param exp:
:return:
"""
ret = re.findall('[-+]?\d+(?:\.\d+)?',exp)
res = reduce(lambda a,b:float(a)+float(b),ret)
return res def remove_muldiv(exp):
"""
计算表达式中的所有的乘除法
:param exp:
:return:
"""
while True:
ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?',exp)
if ret:
son_exp = ret.group()
res = mul_div(son_exp)
exp = exp.replace(son_exp,str(res))
else:return exp def cal(exp):
res = remove_muldiv(exp) # 计算乘除
res = exp_fmt(res) # 符号整理
ret = remove_addsub(res) # 计算加减
return ret def main(exp):
exp = exp.replace(' ','')
while True:
ret = re.search('\([^()]+\)', exp)
if ret:
res = cal(ret.group())
exp = exp.replace(ret.group(), str(res))
else: return cal(exp)
exp = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
ret = main(exp)
print(ret)

待续

最新文章

  1. 采用cocos2d-x lua 的listview 实现pageview的翻页效果之上下翻页效果
  2. NYOJ之题目1058部分和问题
  3. enum使用
  4. POJ 3142 The Balance
  5. WordPress添加固定位置的百度分享按钮
  6. C#.net Winform获取文件路径
  7. Node.js的模块载入方式与机制
  8. zookeeper适用场景:如何竞选Master及代码实现
  9. OOP 7大原则
  10. 【linux】linux服务管理
  11. Object:
  12. 将对象格式的style转换为字符串格式
  13. jquery 几点注意事项
  14. 1.promethues监控融入k8s
  15. CSS content换行实现字符点点点loading效果
  16. sed命令替换文件的内容【学习笔记】
  17. 学习笔记:spark Streaming的入门
  18. Vue表单修饰符(lazy,number,trim)
  19. SQL的各种连接Join详解
  20. Windows平台如何部署scrapy

热门文章

  1. 在ASP.NET Core中使用托管启动(hosting startup)程序集,实现批量注册service
  2. 关于 Kafka 的一些面试题目
  3. 一篇文章让你明白CPU缓存一致性协议MESI
  4. 9月最新184道阿里、百度、腾讯、头条Java面试题合集
  5. 小白学 Python 爬虫(22):解析库 Beautiful Soup(下)
  6. Vue.js实现大文件分片md5断点续传
  7. selenium的安装、报错和解决
  8. CentOS 7上的主机名设置和基本网络管理
  9. linux部署.net Core项目
  10. webpack生成的css文件background-image url图片无法加载