題目:
exp = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
如題自己寫計算器,算出以上str中的結果,注意不能用eval函數,哈哈。
大致思路:定義3個函數,
函數1:計算+-*/,最終正則匹配的記過,都要使用此函數計算。
函數2:計算類似1-2+3*4/5,正則先匹配*/,在匹配+-,然后調用函數1算,得出來結果replace掉正則匹配,然后掉函數2遞歸,
函數3:搞最后的大的exp,先正則匹配出括號內的,去調函數2計算,計算的結果在replace,然后調用函數3遞歸。
使用到的方法:遞歸、正則
實現代碼如下:最終計算的結果和eval結果比較一致,說明沒問題
import re
def jianfa(exp):
'''此函數:用於減法計算'''
if exp.count("-")>2:
exp=exp.replace("--","+")
a,b=exp.split("+")
a,b=float(a),float(b)
return a+b
elif exp.count("-")>1:
if "--" in exp:
exp=exp.replace("--","+")
a,b=exp.split("+")
a,b=float(a),float(b)
return a+b
else:
exp=exp.strip("-")
a,b=exp.split("-")
a,b=float(a),float(b)
return 0-(a+b)
else:
exp=exp.strip("-")
a,b=exp.split("-")
a,b=float(a),float(b)
return a-b
def jisuanqi(exp):
'''此函數:用於加減乘除計算'''
if "*" in exp:
a,b=exp.split("*")
a,b=float(a),float(b)
return a*b
elif "/" in exp:
a,b=exp.split("/")
a,b=float(a),float(b)
return a/b
elif "+" in exp:
a,b=exp.split("+")
a,b=float(a),float(b)
return a+b
elif "-" in exp:
return jianfa(exp)
def compute_replace(exp,ret):
'''此函數:用於調用jisuanqi,然后得出的記過然后替換正則匹配的結果'''
new_ret = jisuanqi(ret)
new_ret = str(new_ret)
new_exp = exp.replace(ret, new_ret)
return new_exp
def fmt(exp):
'''此函數:用於去除以下特殊的符號,避免正則匹配出錯'''
while "++" in exp or "--" in exp or "+-" in exp or "-+" in exp:
exp= exp.replace("++","+")
exp= exp.replace("--","+")
exp= exp.replace("+-","-")
exp= exp.replace("-+","-")
return exp
def func_compute(exp):
'''此函數:用於計算如1+2*/5這樣的連續算法,先匹配*/在匹配+-,然后調用jisuanqi計算,並遞歸'''
exp=fmt(exp)
if "*" in exp or "/" in exp:
ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?',exp).group()
new_exp=compute_replace(exp,ret)
t_n_exp = func_compute(new_exp) #計算出的結果,再去遞歸調用本函數
return t_n_exp
elif "+" in exp or "-" in exp:
if exp.startswith("-") and exp.count("-") ==1 and exp.count("+")==0: #考慮如果最后結果為負數,走這個判斷
return exp
ret = re.search('-?\d+(\.\d+)?[+-]\d+(\.\d+)?',exp).group()
new_exp = compute_replace(exp, ret)
t_n_exp = func_compute(new_exp) #計算出的結果,再去遞歸調用本函數
return t_n_exp
else:
return exp
def match(exp):
'''此函數:正則匹先配出括號內的公式,然后去調用上面函數計算,並遞歸'''
exp=exp.replace(" ","")
if "(" in exp:
match_exp=re.search("\([^()]+\)",exp).group()
n_match_exp=match_exp.strip("(")
n_match_exp = n_match_exp.strip(")")
ret=func_compute(n_match_exp)
new_exp=exp.replace(match_exp,ret)
c_new_exp=match(new_exp)
return c_new_exp
else:
return func_compute(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=match(exp)
print(ret)