Python利用正則表達(dá)式實(shí)現(xiàn)計(jì)算器算法思路解析
?。?)不使用eval()等系統(tǒng)自帶的計(jì)算方法
?。?)實(shí)現(xiàn)四則混合運(yùn)算、括號(hào)優(yōu)先級(jí)解析
思路:
1、字符串預(yù)處理,將所有空格去除
2、判斷是否存在括號(hào)運(yùn)算,若存在進(jìn)行第3步,若不存在則直接進(jìn)入第4步
3、利用正則表達(dá)式獲取最底層括號(hào)內(nèi)的四則運(yùn)算表達(dá)式
4、將四則運(yùn)算表達(dá)式進(jìn)行預(yù)處理:表達(dá)式開頭有負(fù)數(shù)時(shí),在表達(dá)式前加上一個(gè)0
5、利用re.split()、re.findall()方法,通過(guò)加減符號(hào),對(duì)四則運(yùn)算進(jìn)行拆分為乘除運(yùn)算式和數(shù)字,并保留對(duì)應(yīng)的位置下標(biāo)。
6、利用re.split()、re.findall()方法,通過(guò)乘除符號(hào),將乘除式拆分為乘除符號(hào)與數(shù)字,然后進(jìn)行計(jì)算,并返回?cái)?shù)值。
7、通過(guò)re.split()、re.findall()保留的下標(biāo)位置,將表達(dá)式還原。
8、完成所有乘除運(yùn)算之后,返回進(jìn)行加減運(yùn)算。
9、完成加減運(yùn)算后,返回表達(dá)式進(jìn)行替代。
10、通過(guò)遞歸函數(shù),完成所有括號(hào)運(yùn)算后。最后再完成一次四則運(yùn)算即可完成所有運(yùn)算。
注:在過(guò)程中,負(fù)數(shù)的處理存在三個(gè)要點(diǎn):當(dāng)負(fù)數(shù)出現(xiàn)在表達(dá)式開頭、負(fù)數(shù)前面存在減法、乘除式中存在負(fù)數(shù)且不在表達(dá)式開頭。
(1)當(dāng)負(fù)數(shù)出現(xiàn)在表達(dá)式開頭:在前面加上一個(gè)0
?。?)負(fù)數(shù)前面存在減法:每次完成一次運(yùn)算后需要進(jìn)行一次符號(hào)檢查替換
(3)乘除式中存在負(fù)數(shù)且不在表達(dá)式開頭:將負(fù)號(hào)移到表達(dá)式最開頭
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Dang import re def update_formula(calc_list,calc_operator_list): # 通過(guò)拆分后的表達(dá)式列表與符號(hào)列表重新組合 for index,item in enumerate(calc_list): if index == 0: formula = item elif index != 0: formula += calc_operator_list[index-1] + item return formula def negative_start_issue(formula): #處理負(fù)數(shù)在括號(hào)內(nèi)表達(dá)式開頭的情形 calc_list = re.split("[+-]",formula) #通過(guò)+-符號(hào)將各個(gè)乘除運(yùn)算分隔出來(lái) calc_operator_list = re.findall("[+-]",formula) for index,item in enumerate(calc_list): if index == 0 and item == '': # 處理負(fù)號(hào)在開頭的問(wèn)題 calc_list[index] = '0' else: calc_list[index] = item.strip() formula = update_formula(calc_list,calc_operator_list) return formula def deal_unusual_issue(formula): # 雙加減符號(hào)處理 formula = formula.replace(" ","") #去掉空格 formula = formula.replace("++","+") formula = formula.replace("+-", "-") formula = formula.replace("-+", "-") formula = formula.replace("--", "+") return formula def deal_negative_issue(formula): # 處理乘除運(yùn)算中負(fù)數(shù)的計(jì)算問(wèn)題(分前后位置兩種情況) # 1.負(fù)數(shù)在后 m = re.search("[0-9]+[.]*[0-9]*[*|/][-][0-9]+[.]*[0-9]*",formula) # minus_pre = re.search("[0-9]+[.]*[0-9]*[*|/][-][0-9]+[.]*[0-9]*",formula).group() # 注意匹配的必要項(xiàng)與非必要項(xiàng),如:"[0-9]+[.][0-9]+[*|/][-][0-9]+[.][0-9]+"誤把非必要項(xiàng)當(dāng)做必要項(xiàng)。 if m: minus_pre = m.group() minus_pro = "-"+minus_pre.replace("-","") formula = formula.replace(minus_pre,minus_pro) if "*-" in formula or "/-" in formula: return deal_negative_issue(formula) # 2.負(fù)數(shù)在前 formula = deal_unusual_issue(formula) return formula def multiply_divide(formula): # print("[%s]"%formula,formula) # 乘除計(jì)算 calc_list = re.split("[*/]", formula) operator_list = re.findall("[*/]", formula) # 將乘號(hào)除號(hào)通過(guò)列表方式分隔出來(lái) # print("sub_calc_list:", sub_calc_list) # print("sub_operator_list:", sub_operator_list) res = 0 for index2, i in enumerate(calc_list): if index2 == 0: res = float(i) else: if operator_list[index2 - 1] == '*': # 通過(guò)sub_operator_list中的index判斷到底是加法還是減法, res *= float(i) elif operator_list[index2 - 1] == '/': res /= float(i) return res def add_abstract(formula): # 加減計(jì)算 # 1.開頭位置負(fù)數(shù)處理 formula = negative_start_issue(formula) # 2.雙加減符號(hào)處理 formula = deal_unusual_issue(formula) # 3.加減邏輯運(yùn)算 calc_list = re.split("[+-]", formula) operator_list = re.findall("[+-]", formula) res = 0 for index, i in enumerate(calc_list): if index == 0: res = float(i) else: if operator_list[index-1] == '+': res += float(i) elif operator_list[index-1] == '-': res -= float(i) return res """
四則混合運(yùn)算主函數(shù)
"""def elementary_arithmetic(formula): # 負(fù)數(shù)處理 formula = negative_start_issue(formula) formula = deal_negative_issue(formula) # 乘除運(yùn)算 calc_list = re.split("[+-]",formula) # 通過(guò)+-符號(hào)將各個(gè)乘除運(yùn)算分隔出來(lái) calc_operator_list = re.findall("[+-]",formula) for index1, item in enumerate(calc_list): calc_list[index1] = str(multiply_divide(item)) #數(shù)據(jù)類型的強(qiáng)制轉(zhuǎn)換!??! formula = update_formula(calc_list,calc_operator_list) # 加減運(yùn)算 formula = add_abstract(formula) return formula """ 括號(hào)運(yùn)算 """ def calculator(formula): #數(shù)據(jù)預(yù)處理 formula = formula.replace(" ","") m = re.search("\([^()]*\)",formula) # 判斷是否需要進(jìn)行括號(hào)運(yùn)算 if m: # 括號(hào)運(yùn)算 # 提取最小括號(hào)運(yùn)算式,計(jì)算結(jié)果,并返回。 subformula = m.group().strip("()") # 把找出來(lái)的括號(hào)剝離 print("subformula:",subformula,type(subformula)) subres = elementary_arithmetic(subformula) # 調(diào)用四則混合運(yùn)算主函數(shù) print("subres:",subres) formula = formula.replace(m.group(), str(subres)) print("updated formula:",formula) if "(" in formula: return calculator(formula) else: print("formula result:",formula) # 除去所有括號(hào)后可能出現(xiàn):1-2*-312.8 formula = elementary_arithmetic(formula) return formula else: return elementary_arithmetic(formula) # 以下為測(cè)試代碼: formula = "1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*9/4*28 +10 * 56/14 )) - (-4*3)/ (16-3*2) )" print("%s = "%formula,calculator(formula))
總結(jié)
以上所述是小編給大家介紹的Python利用正則表達(dá)式實(shí)現(xiàn)計(jì)算器算法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Python基于遞歸算法實(shí)現(xiàn)的走迷宮問(wèn)題
這篇文章主要介紹了Python基于遞歸算法實(shí)現(xiàn)的走迷宮問(wèn)題,結(jié)合迷宮問(wèn)題簡(jiǎn)單分析了Python遞歸算法的定義與使用技巧,需要的朋友可以參考下2017-08-08使用Python中Tkinter模塊的Treeview?組件顯示ini文件操作
這篇文章主要介紹了使用Python中Tkinter模塊的Treeview組件顯示ini文件操作,Treeview組件位于ttk模塊,該模塊自Tk8.5開始引入,主題詳細(xì)介紹,需要的朋友可以參考一下2022-09-09Python讀取本地文件并解析網(wǎng)頁(yè)元素的方法
今天小編就為大家分享一篇Python讀取本地文件并解析網(wǎng)頁(yè)元素的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05