用Python代码写的计算器
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)
待续