設計目標
實現加減乘除及拓號優先級解析 用戶輸入'1 - 2 * ( (6-3 +(-5/5)*(9-2*3/3 + 7/3*7/4*12 +10 * 5/5 )) - (-4*3)/ (12-3*2) )'等類似公式后, 必須自己解析里面的(),+,-,*,/符號和公式,運算后得出結果,結果必須與真實的計算器所得出的結果一致
流程圖:
代碼:
1、主文件
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2017/10/18 22:26 # @Author : Evescn # @Site : # @File : mian.py # @Software: PyCharm import re def multi_or_divi(string): # 乘除法函數 # 去掉括號 calc_list = re.search("[^()]+", string) # 以乘除符號分割 sub_calc_list = re.split("[*/]", calc_list.group()) # 獲取到字符串中的乘除符號 sub_operator_list = re.findall("[*/]", calc_list.group()) sub_res = None for index in range(len(sub_calc_list)): if sub_res: if sub_operator_list[index-1] == "*": sub_res *= float(sub_calc_list[index]) else: sub_res /= float(sub_calc_list[index]) else: sub_res = float(sub_calc_list[index]) return float(sub_res) def add_or_sub(string): # 加減法函數 # 去掉括號 calc_list = re.search("[^()]+", string) # 以加減符號分割 sub_calc_list = re.split("[+-]", calc_list.group()) # 獲取到字符串中的加減符號 sub_operator_list = re.findall("[+-]", calc_list.group()) # 如果字符串已減號開頭,需要特殊處理 if re.match("[-+]", calc_list.group()): if sub_operator_list[0] == "-": sub_calc_list[1] = -float(sub_calc_list[1]) # 對sub_operator_list和sub_calc_list進行字符串切割,或者到正確數據 sub_operator_list = sub_operator_list[1:] sub_calc_list = sub_calc_list[1:] # 對字符串切割后,如何sub_calc_list為空,表示傳過來的數為-X,直接返回sub_calc_list[0]即可,無需乘除運算 if len(sub_operator_list) == 0: return sub_calc_list[0] sub_res = None for index in range(len(sub_calc_list)): if sub_res: if sub_operator_list[index-1] == "+": sub_res += float(sub_calc_list[index]) else: sub_res -= float(sub_calc_list[index]) else: sub_res = float(sub_calc_list[index]) return float(sub_res) def deal_minus_issue(ret): # 處理減法字符串 # 創建一個新字符串用於返回處理后的字符串 new_ret = [] for index, item in enumerate(ret): if item.endswith("*") or item.endswith("/"): new_ret.append("%s-%s" %(ret[index], ret[index+1])) elif re.search("[*/]", ret[index]): new_ret.append(ret[index]) return new_ret def main(): # 輸入字符串 a = '1 - 2 * ( (6-3 +(-5/5)*(9-2*3/3 + 7/3*7/4*12 +10 * 5/5 )) - (-4*3)/ (12-3*2) )' # a = '+(-40/5+3*(-12))' # 去空格 a = a.replace(" ", "") # 設置循環退出的條件 count = 2 while True and count > 0: # 最內行括號 calc_list = re.search(r'\([^()]+\)', a) if calc_list: # 如果能取到括號,把正則匹配結果賦值給calc_list_value calc_list_value = calc_list.group() else: # 如果不能取到括號,說明已經沒有括號了,這只有加減乘除,對多只需要2次計算即可得出結果 # 把a字符串賦值給calc_list_value count -= 1 calc_list_value = a if "+" in calc_list_value or "-" in calc_list_value: if "*" in calc_list_value or "/" in calc_list_value: # 去掉括號以便以加減符號分割字符串 calc_list1 = re.findall(r'[^()]+', calc_list_value) # 以加減符號去分割 calc_list2 = re.split(r'[-+]', calc_list1[0]) # 調用處理減法字符串函數,處理下*-或者/-這類問題 calc_list2 = deal_minus_issue(calc_list2) # 返回后的calc_list列表只有包含乘除的式子 for item in calc_list2: # 對每一個乘除調用乘除函數 value = multi_or_divi(item) # 把計算后的結果替換掉原來的值 a = a.replace(item, str(value)) # 處理下字符串中出現的++或+-問題 a = a.replace("+-", "-") a = a.replace("--", "+") else: # 式子中沒有乘除符號,那就只有加減符號,調用加減函數 value = add_or_sub(calc_list_value) # 把計算后的結果替換掉原來的值 a = a.replace(calc_list_value, str(value)) # 處理下字符串中出現的++或+-問題 a = a.replace("+-", "-") a = a.replace("--", "+") else: if "*" in calc_list_value or "/" in calc_list_value: # 式子中沒有加減符號,那就只有乘除符號,調用處理減法字符串函數,處理下*-或者/-這類問題 value = multi_or_divi(calc_list_value) # 把計算后的結果替換掉原來的值 a = a.replace(calc_list_value, str(value)) # 處理下字符串中出現的++或+-問題 a = a.replace("+-", "-") a = a.replace("--", "+") print("a:", a) if __name__ == '__main__': main()
2、運行結果
a: 1-2*((6-3+(-1.0)*(9-2*3/3+7/3*7/4*12+10*1.0))-(-4*3)/(12-3*2)) a: 1-2*((6-3-1.0*(9-2*3/3+7/3*7/4*12+10*1.0))-(-4*3)/(12-3*2)) a: 1-2*((6-3-1.0*(9-2.0+49.00000000000001+10.0))-(-4*3)/(12-3*2)) a: 1-2*((6-3-1.0*66.0)-(-4*3)/(12-3*2)) a: 1-2*((6-3-66.0)-(-4*3)/(12-3*2)) a: 1-2*(-63.0-(-4*3)/(12-3*2)) a: 1-2*(-63.0-(-12.0)/(12-3*2)) a: 1-2*(-63.0+12.0/(12-3*2)) a: 1-2*(-63.0+12.0/(12-6.0)) a: 1-2*(-63.0+12.0/6.0) a: 1-2*(-63.0+2.0) a: 1-2*-61.0 a: 1+122.0 a: 123.0