網站首頁 編程語言 正文
本文實例為大家分享了python實現簡易計算器功能的具體代碼,供大家參考,具體內容如下
一、功能目標
用戶輸入一個類似 ?1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) ?這樣的表達式,假設表達式里面除了包含空格、'+'、'-'、'*'、'/'和括號再無其他特殊符號,然后自己動手寫代碼解析其中的表達式,實現加減乘除,最后得出的結果與真實的計算機所算的結果必須一致。
二、解題思路
1、為了分開運算符和數字,因此把輸入的字符串格式轉換為 列表的格式進行處理,這樣子就可以按位進行 處理了
2、實現功能的核心點在于括號、乘除、加減的優先級排序,因此我們先想辦法一層一層的去括號,即從最里層的括號開始計算,然后去掉第一層括號,然后一直繼續這個 過程,最后得到一個沒有括號的列表,再進行計算得出結果
3、去括號方式:最內層的括號內的表達式就可以當做一個無括號表達式,通過先 運算出乘除,再運算出加減得出整個括號內的值,用這個結果值整體替換括號內的內容即實現了去一層括號,然后通過遞歸去除所有的括號
4、去除乘除號方式:見 remove_multiplication_division(eq) 函數部分
5、去除加減號 方式:見 remove_plus_minus(eq) 函數部分
三、函數說明
1、主函數
def caculator(eq): ? ? format_list = eq_format(eq) ?# 把字符串變成格式化列表形式 ? ? s_eq = simplify(format_list) # 去括號,得到無括號的一個格式化列表 ? ? ans = calculate(s_eq) ? ? ? ?# 計算最終結果 ? ? if len(ans) == 2: ? ? ? ? ? ?# 判斷最終結果為正數還是負數 ? ? ? ? ans = -float(ans[1]) ? ? else: ? ? ? ? ans = float(ans[0]) ? ? return ans
2、eq_format( )函數
def caculator(eq): ? ? format_list = eq_format(eq) ?# 把字符串變成格式化列表形式 ? ? s_eq = simplify(format_list) # 去括號,得到無括號的一個格式化列表 ? ? ans = calculate(s_eq) ? ? ? ?# 計算最終結果 ? ? if len(ans) == 2: ? ? ? ? ? ?# 判斷最終結果為正數還是負數 ? ? ? ? ans = -float(ans[1]) ? ? else: ? ? ? ? ans = float(ans[0]) ? ? return ans
2.1 這個函數的作用是把輸入的算式通過re模塊,用正則表達式把算術符號和數字分開。
2.2 ?[\d\.]+ | |\+|\-|\*|\/||\+|\-|\*|\/|意思:按管道符號 | (| 表示 或 的意思)可分為幾部分,[\d\.]+ ?是指匹配數字或小數點一次或多次,是指左括號,\+是指加號,\-是指減號,\*是指乘號,\/是指除號,是指左括號,\+是指加號,\-是指減號,\*是指乘號,\/是指除號, 是指右括號,整個正則表達式會把字符串變成類似['(','6','*','5','-''7',')' ]這樣子的格式列表
3、simplify( ) 函數
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) ? ? # 解決去括號后會出現的-- ?+- 問題 ? ? ? ? ? ? return simplify(format_list) ? ? ? ? ? ?# 遞歸去括號 ? ? ? ? count = count + 1 ? ? return format_list ? ?? # 當遞歸到最后一層的時候,不再有括號,因此返回列表
3.1 這個函數的作用是:把輸入的帶有括號的格式化列表,用遞歸的方式去除括號,每一次遞歸去一個括號, 直到沒有括號則返回去完括號的格式化列表
3.2 找到最內層括號的方法:遍歷列表,如果遇到左括號,則把當前左括號的索引賦值給參數bracket,直到遇到第一個右括號,此時的索引與bracket中間的元素即為最內層括號的元素,用切片的方式提取出來,通過 calculate() 函數計算出值,然后用計算結果去替換掉此時左括號到第一個右括號的元素,此時去除第一層括號,然后進入遞歸,不斷遞歸直至去除所有括號
3.3 可能遇到的問題:
首先是不要用index的方式去取當前左括號的索引,因為列表的index方法返回的一直都是第一個左括號的索引,而不是當前左括號的索引,會導致出錯。因此我在函數內用參數 count 進行計數當前索引值。
然后是用計算得出的值來替換掉第一層括號部分后,有可能會出現 ‘+-’ ,‘ - -’的情況,要記得處理,我的函數中寫了一個change() 函數進行處理
4、caculate()函數
def calculate(s_eq): ? ? ''' ? ? :param s_eq: 不帶括號的格式化列表 ? ? :return: 計算結果 ? ? ''' ? ? 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
這個函數的作用是輸入不帶括號的格式化列表, 輸出計算結果,然后返回結果列表
思路是先算乘除:remove_multiplication_division()函數,然后再從頭到尾計算加減法:remove_plus_minus( )函數
5、remove_multiplication_division()函數
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
這個函數的作用是計算乘除,去乘除號。方法也是遞歸的方法,每次處理完一個乘號或者除號都可能出現符號問題,記得處理后再進入下一次遞歸
6、remove_plus_minus( )函數
def remove_plus_minus(eq): ? ? ''' ? ? :param eq: 只帶有加減號的格式化列表 ? ? :return: 計算出整個列表的結果 ? ? ''' ? ? 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
這個函數輸入一個只有加減號的格式化列表,然后從頭到尾的計算,得出最終結果,返回最終結果(結果形式也是列表)
7、change()函數
def change(eq,count): ? ? ''' ? ? :param eq: 剛去完括號或者乘除后的格式化列表 ? ? :param count: 發生變化的元素的索引 ? ? :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
這個函數的作用是解決符號輸入兩個問題。輸入參數1:剛去完括號的或者剛 計算完乘除的 格式化列表,輸入參數2: 列表元素發生變化的索引(如去括號時,這個索引則為去括號前列表的最內層左括號的索引),輸出結果是一個處理完符號問題或者什么都不做直接返回的列表
四、完整代碼
import re ? def eq_format(eq): ? ? ''' ? ? :param eq: 輸入的算式字符串 ? ? :return: 格式化以后的列表,如['60','+','7','*','8'] ? ? ''' ? ? format_list = re.findall('[\d\.]+|\(|\+|\-|\*|\/|\)',eq) ? ? return format_list ? def change(eq,count): ? ? ''' ? ? :param eq: 剛去完括號或者乘除后的格式化列表 ? ? :param count: 發生變化的元素的索引 ? ? :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 ? ? 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 ? ? def remove_plus_minus(eq): ? ? ''' ? ? :param eq: 只帶有加減號的格式化列表 ? ? :return: 計算出整個列表的結果 ? ? ''' ? ? 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 ? def calculate(s_eq): ? ? ''' ? ? :param s_eq: 不帶括號的格式化列表 ? ? :return: 計算結果 ? ? ''' ? ? 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 ? ? 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) ? ? # 解決去括號后會出現的-- ?+- 問題 ? ? ? ? ? ? return simplify(format_list) ? ? ? ? ? ?# 遞歸去括號 ? ? ? ? count = count + 1 ? ? return format_list ? ? ? ? ? ? ? ? ? ? # 當遞歸到最后一層的時候,不再有括號,因此返回列表 ? ? def caculator(eq): ? ? format_list = eq_format(eq) ? ? s_eq = simplify(format_list) ? ? ans = calculate(s_eq) ? ? if len(ans) == 2: ? ? ? ? ans = -float(ans[1]) ? ? else: ? ? ? ? ans = float(ans[0]) ? ? return ans ? ? if __name__ == '__main__':? ? ? equation = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))' ? ? ans = caculator(equation) ? ? print('eval運算結果:',eval(equation)) ? ? print('程序運算結果:',ans)
程序運行結果
原文鏈接:https://blog.csdn.net/a971956955/article/details/81489914
相關推薦
- 2023-02-07 Android?Service完整實現流程分析_Android
- 2023-07-25 SpringBoot配置AOP
- 2023-04-12 Blazor實現組件嵌套傳遞值的示例詳解_其它綜合
- 2022-06-06 typescript中abstractClass(抽象類)、extends、abstract
- 2023-05-19 Kotlin?this關鍵字的使用實例詳解_Android
- 2022-03-31 C語言中冒泡排序算法詳解_C 語言
- 2022-04-10 python中的單向鏈表實現_python
- 2022-08-19 python?return實現匯率轉換器教程示例_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支