您好,登錄后才能下訂單哦!
本篇文章為大家展示了使用python實現(xiàn)一個簡單計算器,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
用戶輸入一個類似 1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) 這樣的表達式,假設(shè)表達式里面除了包含空格、'+'、'-'、'*'、'/'和括號再無其他特殊符號,然后自己動手寫代碼解析其中的表達式,實現(xiàn)加減乘除,最后得出的結(jié)果與真實的計算機所算的結(jié)果必須一致。
1、為了分開運算符和數(shù)字,因此把輸入的字符串格式轉(zhuǎn)換為 列表的格式進行處理,這樣子就可以按位進行 處理了
2、實現(xiàn)功能的核心點在于括號、乘除、加減的優(yōu)先級排序,因此我們先想辦法一層一層的去括號,即從最里層的括號開始計算,然后去掉第一層括號,然后一直繼續(xù)這個 過程,最后得到一個沒有括號的列表,再進行計算得出結(jié)果
3、去括號方式:最內(nèi)層的括號內(nèi)的表達式就可以當(dāng)做一個無括號表達式,通過先 運算出乘除,再運算出加減得出整個括號內(nèi)的值,用這個結(jié)果值整體替換括號內(nèi)的內(nèi)容即實現(xiàn)了去一層括號,然后通過遞歸去除所有的括號
4、去除乘除號方式:見 remove_multiplication_division(eq) 函數(shù)部分
5、去除加減號 方式:見 remove_plus_minus(eq) 函數(shù)部分
1、主函數(shù)
def caculator(eq): format_list = eq_format(eq) # 把字符串變成格式化列表形式 s_eq = simplify(format_list) # 去括號,得到無括號的一個格式化列表 ans = calculate(s_eq) # 計算最終結(jié)果 if len(ans) == 2: # 判斷最終結(jié)果為正數(shù)還是負數(shù) ans = -float(ans[1]) else: ans = float(ans[0]) return ans
2、eq_format( )函數(shù)
def eq_format(eq): ''' :param eq: 輸入的算式字符串 :return: 格式化以后的列表,如['60','+','7','*','8'] ''' format_list = re.findall('[\d\.]+|\(|\+|\-|\*|\/|\)',eq) return format_list
2.1 這個函數(shù)的作用是把輸入的算式通過re模塊,用正則表達式把算術(shù)符號和數(shù)字分開。
2.2 [\d\.]+ | \( | \+ | \- | \* | \/ | \)意思:按管道符號 | (| 表示 或 的意思)可分為幾部分,[\d\.]+ 是指匹配數(shù)字或小數(shù)點一次或多次,\(是指左括號,\+ 是指 加號,\- 是指減號,\* 是指乘號,\/ 是指除號, \) 是指右括號,整個正則表達式會把字符串變成類似['(','6','*','5','-''7',')' ]這樣子的格式列表
3、simplify( ) 函數(shù)
def simplify(format_list): ''' :param format_list: 輸入的算式格式化列表如['60','+','7','*','8'] :return: 通過遞歸去括號,返回簡化后的列表 ''' bracket = 0 # 用于存放左括號在格式化列表中的索引 count = 0 for i in format_list: if i == '(': bracket = count elif i == ')': temp = format_list[bracket + 1 : count] # print(temp) new_temp = calculate(temp) format_list = format_list[:bracket] + new_temp + format_list[count+1:] format_list = change(format_list,bracket) # 解決去括號后會出現(xiàn)的-- +- 問題 return simplify(format_list) # 遞歸去括號 count = count + 1 return format_list # 當(dāng)遞歸到最后一層的時候,不再有括號,因此返回列表
3.1 這個函數(shù)的作用是:把輸入的帶有括號的格式化列表,用遞歸的方式去除括號,每一次遞歸去一個括號, 直到?jīng)]有括號則返回去完括號的格式化列表
3.2 找到最內(nèi)層括號的方法:遍歷列表,如果遇到左括號,則把當(dāng)前左括號的索引賦值給參數(shù)bracket,直到遇到第一個右括號,此時的索引與bracket中間的元素即為最內(nèi)層括號的元素,用切片的方式提取出來,通過 calculate() 函數(shù)計算出值,然后用計算結(jié)果去替換掉此時左括號到第一個右括號的元素,此時去除第一層括號,然后進入遞歸,不斷遞歸直至去除所有括號
3.3 可能遇到的問題:
首先是不要用index的方式去取當(dāng)前左括號的索引,因為列表的index方法返回的一直都是第一個左括號的索引,而不是當(dāng)前左括號的索引,會導(dǎo)致出錯。因此我在函數(shù)內(nèi)用參數(shù) count 進行計數(shù)當(dāng)前索引值。
然后是用計算得出的值來替換掉第一層括號部分后,有可能會出現(xiàn) ‘+-' ,‘ - -'的情況,要記得處理,我的函數(shù)中寫了一個change() 函數(shù)進行處理
4、caculate()函數(shù)
def calculate(s_eq): ''' :param s_eq: 不帶括號的格式化列表 :return: 計算結(jié)果 ''' if '*' or '/' in s_eq: s_eq = remove_multiplication_division(s_eq) if '+' or '-' in s_eq: s_eq = remove_plus_minus(s_eq) return s_eq
這個函數(shù)的作用是輸入不帶括號的格式化列表, 輸出計算結(jié)果,然后返回結(jié)果列表
思路是先算乘除:remove_multiplication_division()函數(shù),然后再從頭到尾計算加減法:remove_plus_minus( )函數(shù)
5、remove_multiplication_division()函數(shù)
def remove_multiplication_division(eq): ''' :param eq: 帶有乘除號的格式化列表 :return: 去除了乘除號的格式化列表 ''' count = 0 for i in eq: if i == '*': if eq[count+1] != '-': eq[count-1] = float(eq[count-1]) * float(eq[count+1]) del(eq[count]) del(eq[count]) elif eq[count+1] == '-': eq[count] = float(eq[count-1]) * float(eq[count+2]) eq[count-1] = '-' del(eq[count+1]) del(eq[count+1]) eq = change(eq,count-1) return remove_multiplication_division(eq) elif i == '/': if eq[count+1] != '-': eq[count-1] = float(eq[count-1]) / float(eq[count+1]) del(eq[count]) del(eq[count]) elif eq[count+1] == '-': eq[count] = float(eq[count-1]) / float(eq[count+2]) eq[count-1] = '-' del(eq[count+1]) del(eq[count+1]) eq = change(eq,count-1) return remove_multiplication_division(eq) count = count + 1 return eq
這個函數(shù)的作用是計算乘除,去乘除號。方法也是遞歸的方法,每次處理完一個乘號或者除號都可能出現(xiàn)符號問題,記得處理后再進入下一次遞歸
6、remove_plus_minus( )函數(shù)
def remove_plus_minus(eq): ''' :param eq: 只帶有加減號的格式化列表 :return: 計算出整個列表的結(jié)果 ''' count = 0 if eq[0] != '-': sum = float(eq[0]) else: sum = 0.0 for i in eq: if i == '-': sum = sum - float(eq[count+1]) elif i == '+': sum = sum + float(eq[count+1]) count = count + 1 if sum >= 0: eq = [str(sum)] else: eq = ['-',str(-sum)] return eq
這個函數(shù)輸入一個只有加減號的格式化列表,然后從頭到尾的計算,得出最終結(jié)果,返回最終結(jié)果(結(jié)果形式也是列表)
7、change()函數(shù)
def change(eq,count): ''' :param eq: 剛?cè)ネ昀ㄌ柣蛘叱顺蟮母袷交斜? :param count: 發(fā)生變化的元素的索引 :return: 返回一個不存在 '+-' ,'--'類的格式化列表 ''' if eq[count] == '-': if eq[count-1] == '-': eq[count-1] = '+' del eq[count] elif eq[count-1] == '+': eq[count-1] = '-' del eq[count] return eq
這個函數(shù)的作用是解決符號輸入兩個問題。輸入?yún)?shù)1:剛?cè)ネ昀ㄌ柕幕蛘邉?計算完乘除的 格式化列表,輸入?yún)?shù)2: 列表元素發(fā)生變化的索引(如去括號時,這個索引則為去括號前列表的最內(nèi)層左括號的索引),輸出結(jié)果是一個處理完符號問題或者什么都不做直接返回的列表
上述內(nèi)容就是使用python實現(xiàn)一個簡單計算器,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。