計算器開發需求
- 實現加減乘除及拓號優先級解析
- 用戶輸入 1 - 2 * ( (60-30 +(-40/5) * (9-25/3 + 7 /399/42998 +10 * 568/14 )) - (-43)/ (16-32) )等類似公式後,必須自己解析裏面的(),+,-,,/符號和公式,運算後得出結果,結果必須與真實的計算器所得出的結果一致
思路:
- 字符串預處理,將所有空格去除
- 判斷是否存在括號運算,若存在進行第3步,若不存在則直接進入第4步
- 利用正則表達式獲取最底層括號內的四則運算表達式
- 利用re.split()、re.findall()方法,通過加減符號,對四則運算進行拆分爲乘除運算式和數字
- 判斷表達式開頭有負數時,如果有,將負號放在第二個值中
- 利用re.split()、re.findall()方法,通過乘除符號,將乘除式拆分爲乘除符號與數字,然後進行計算,並返回數值
- 完成所有乘除運算之後,返回進行加減運算
- 完成加減運算後,返回表達式進行替代
- 通過遞歸函數,完成所有括號運算後。最後再完成一次四則運算即可完成所有運算
# Author: 73
'''
1、字符串預處理,將所有空格去除
2、判斷是否存在括號運算,若存在進行第3步,若不存在則直接進入第4步
3、利用正則表達式獲取最底層括號內的四則運算表達式
4、利用re.split()、re.findall()方法,通過加減符號,對四則運算進行拆分爲乘除運算式和數字
5、判斷表達式開頭有負數時,如果有,將負號放在第二個值中
6、利用re.split()、re.findall()方法,通過乘除符號,將乘除式拆分爲乘除符號與數字,然後進行計算,並返回數值
7、完成所有乘除運算之後,返回進行加減運算
8、完成加減運算後,返回表達式進行替代
9、通過遞歸函數,完成所有括號運算後。最後再完成一次四則運算即可完成所有運算
'''
import re
def compute_multiply_and_dividend(i):
print(i)
operators = re.findall('[*/]', i)
calc_list = re.split('[*/]', i)
res = None
for index, j in enumerate(calc_list):
if res:
if operators[index - 1] == '*':
res *= float(j)
elif operators[index - 1] == '/':
res /= float(j)
else:
res = float(j)
print("\033[31;1m[%s]運算結果等於==\033[0m" % i, res)
return res
def remove_duplicates(formula): # -9-2-5-2*3-5/3-40*4/2-3/5+6*3
formula = formula.replace("++", "+")
formula = formula.replace("+-", "-")
formula = formula.replace("-+", "-")
formula = formula.replace("--", "+")
return formula
def handle_special_occactions(plus_and_minus_operators, multiply_and_dividend):
'''有時會出現這種情況 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...後面這段實際是 2*-14969036.7968254,需要特別處理下'''
for index, i in enumerate(multiply_and_dividend):
#i = i.strip()
if i.endswith('*') or i.endswith('/'):
multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + multiply_and_dividend[index+1]
del multiply_and_dividend[index+1]
del plus_and_minus_operators[index]
return plus_and_minus_operators, multiply_and_dividend
def compute(s):
'''這裏計算的是不帶括號的公式'''
s = s.strip("()") # 取出外面包的括號
s = remove_duplicates(s) # 去除外重複的+-號
plus_and_minus_operators = re.findall('[+-]', s) # 取出所有的+-
print(plus_and_minus_operators)
multiply_and_dividend = re.split('[+-]', s) # 取出乘除公式
print(multiply_and_dividend)
if len(multiply_and_dividend[0]) == 0: # 代表這個肯定是減號
multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
del multiply_and_dividend[0]
del plus_and_minus_operators[0]
plus_and_minus_operators, multiply_and_dividend = handle_special_occactions(plus_and_minus_operators, multiply_and_dividend)
print('aaa', plus_and_minus_operators, multiply_and_dividend)
for index, i in enumerate(multiply_and_dividend):
if re.search('[*/]', i):
sub_res = compute_multiply_and_dividend(i)
multiply_and_dividend[index] = sub_res
print(multiply_and_dividend, plus_and_minus_operators)
total_res = None
for index, i in enumerate(multiply_and_dividend):
if total_res: # 代表不是第一次
if plus_and_minus_operators[index-1] == '+':
total_res += float(i)
elif plus_and_minus_operators[index-1] == '-':
total_res -= float(i)
else:
total_res = float(i)
print("\033[31;1m[%s]運行結果:\033[0m" % s, total_res)
return total_res
def calc(s):
'''計算機程序主入口,優先級:括號>乘除>加減'''
s = s.replace(" ", "") # 去除所有的空格
print(s)
flag = True
while flag:
# 找到最裏層的括號
m = re.search("\([^()]*\)", s)
if m:
print("先算括號裏的值:", m.group())
sub_res = compute(m.group())
s = s.replace(m.group(), str(sub_res))
else:
print('\033[41;1m----沒拓號了...---\033[0m')
print(s)
print('\n\n\033[42:1m最終結果:\033[0m', compute(s))
flag = False # 代表公式裏的拓號都沒了
if __name__ == "__main__":
calc("1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")