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)))