练习-表达式计算(多层括号,加,减,乘,除,整除,取余,幂)
import re # 运算字典 calc = { '+': lambda x, y: x + y, # 加 '-': lambda x, y: x - y, # 减 '*': lambda x, y: x * y, # 乘 '/': lambda x, y: x / y, # 除 '%': lambda x, y: x % y, # 取余数 '//': lambda x, y: x // y, # 整除 '^': lambda x, y: x ** y # 幂(不知道是不是bug,方式不同结果不同,最下面有演示) } # 判断优先级函数 def order(lis=[]): # 列表开头有'-'说明第一个数是负数 if lis[0] == '-': lis.pop(0) lis[0] = -float(lis[0]) while len(lis) != 1: # 未得到最终结果就继续执行 for i in range(len(lis)): # 判断是否运算符 muldiv = re.search(r'[\^*/%+-]/?$', str(lis[i])) if muldiv: # 判断当前是否加,减运算 if re.search(r'[+-]', str(lis[i])): # 判断后续是否有优先级高的幂,乘,除,求余,整除运算 if re.search(r'[\^*/%]/?', str(lis)): continue # 判断当前是否乘,除,求余,整除运算 elif re.search(r'[*/%]/?', str(lis[i])): # 判断后续是否有优先级高的幂运算 if re.search(r'[\^]', str(lis)): continue num1 = float(lis[i - 1]) # 取参数1 # 在i是符号的情况下,出现'-',说明下个数是负数, if lis[i + 1] == '-': lis.pop(i + 1) lis[i + 1] = -float(lis[i + 1]) num2 = float(lis[i + 1]) # 取参数2 result = calc[muldiv.group()](num1, num2) # 按运算符进行运算 for m in range(2): # 删除已运算完的表达式 lis.pop(i) lis[i - 1] = result # 将结果加入表达式 break # 返回重新开始,因为索引位置已发生改变,不适合继续取值 return lis # 主函数 def operation(exp): # 统一格式化表达式 exp = exp.replace(' ', '').replace(')(', ')*(') exp = exp.replace('++', '+').replace('--', '+') exp = exp.replace('+-', '-').replace('-+', '-') exp = exp.replace('**', '^') # 正则分割字符串 exp = re.findall(r'\d+(?:\.\d+)?|[\D+]/?', exp) while '(' in exp: # 判断有没有括号 # 用循环来寻找匹配的括号,执行完括号内表达式就退出循环 for i in range(len(exp)): if exp[i] == '(': if i > 0 and re.search(r'\d+(?:\.\d+)?', str(exp[i - 1])): exp.insert(i, '*') # 将类似2()形式的,改成2*()形式 break start = i # 记录最后一个"("位置 elif exp[i] == ')': fir = exp[:start] # 切片列表左边 mid = exp[start + 1:i] # 切片要计算的中间列表 end = exp[i + 1:] # 切片列表右边 mid = order(mid) # 判断优先级计算,得出计算结果 exp = fir + mid + end # #将括号内表达式计算完后,进行列表拼接 print(str(exp).replace(',', '').replace("'", '')) break # 跳出for循环,不再进行下一组括号计算(因为原列表已改变,索引也改变,不适合下次取值) else: # 没括号,直接执行计算 order(exp) return float(exp[0]) if __name__ == '__main__': l = "-2.5*((3.562**2 + 5*-60//-2)*(3*-5/6-9%-10//3))" # 分解步骤如下 # - 2.5 * (162.68784399999998 * (3 * - 5 / 6 - 9 % - 10 // 3)) # - 2.5 * (162.68784399999998 * -1.5) # - 2.5 * -244.03176599999998 # 610.0794149999999 ret = operation(l) print('内置函数:%s' % eval(l)) print('自写函数:%s' % ret) # 同样都是幂运算,结果却不相同 num1 = -3.562 num2 = 8 print('eval:%F 数字:%F 变量:%F POW:%F' % (eval('-3.562**8'), -3.562**8, num1**num2, pow(-3.562, 8)))