需求:實現能計算類似 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等類似公式的計算器程序
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Xiaobai Lei
import re
def atom_cal(m_str):
"""最小計算單位"""
if "*" in m_str:
m1,m2 = m_str.split("*")
return str(float(m1) * float(m2))
elif "/" in m_str:
m1,m2 = m_str.split("/")
return str(float(m1)/float(m2))
def format_str(f_str):
"""格式化字符串"""
f_str = f_str.replace("++","+")
f_str = f_str.replace("+-","-")
f_str = f_str.replace("--","+")
f_str = f_str.replace("-+","-")
return f_str
def mul_div(exp):
"""計算乘除"""
while True:
exp_res = re.search(r"\d+(\.\d+)?[*/]-?\d+(\.\d+)?", exp) # 找出乘除法的表達式
if exp_res:
atom_exp = exp_res.group() # group取出最小的表達式
res = atom_cal(atom_exp) # 計算最小單位乘除得到結果
exp = exp.replace(atom_exp, res) # 將結果替換回原來的字符串
else:
return str(exp)
def add_sub(exp):
"""計算加減"""
exp_sum = 0
while True:
exp_res = re.findall(r"-?\d+(?:\.\d+)?", exp) # 用findall將符號連帶數字一起找出來,直接相加就行了,這樣還省去了去括號的麻煩,這個思想不錯
if exp_res:
for i in exp_res:
exp_sum += float(i)
return exp_sum
def cal(exp):
"""計算加減乘除並返回值"""
exp = mul_div(exp) # 先計算乘除
exp = format_str(exp) # 格式化字符串
exp = add_sub(exp) # 計算加減
return exp
def main(exp):
exp = exp.replace(' ','') # 先去空格
while True:
exp_res = re.search(r"\([^()]+\)", exp) # 找括號
if exp_res:
exp_group = exp_res.group() # 取值
cal_res = cal(exp_group) #計算括號內的值,返回數值結果
exp = exp.replace(exp_group, str(cal_res)) # 在這里str轉字符串而不是在返回值轉是因為想最終返回給用戶的計算值為float類型
else:
return cal(exp)
s = "1 +3*2/4- 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
print(eval(s)) # python計算出來的結果
print(main(s)) # 自己寫的計算出來的結果