#!/usr/bin/env python # -*- coding:utf-8 -*- import sys import re def welcome_func(): """ 輸入判斷 :param expression: 表達式 :return: 返回有效表達式 """ welcome_str = "超級計算器" print(welcome_str.center(50,'*'),'\n') # 輸出歡迎界面 while True: iput = input("請輸入你要計算的表達式[q:退出]:").strip() if iput == 'q': # 退出計算 sys.exit("bye-bye") elif len(iput) == 0: continue else: iput = re.sub('\s*', '', iput) # 去除空格 return iput def chengchu(expression): """ 乘除運算 :param expression: 表達式 :return: 返回沒有乘除的表達式/最終計算結果 """ val = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression) # 匹配乘除號 if not val: # 乘除號不存在,返回輸入的表達式 return expression data = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression).group() # 匹配乘除號 if len(data.split('*')) > 1: # 當可以用乘號分割,證明有乘法運算 part1, part2 = data.split('*') # 以乘號作為分割符 value = float(part1) * float(part2) # 計算乘法 else: part1, part2 = data.split('/') # 用除號分割 if float(part2) == 0: # 如果分母為0,則退出計算 sys.exit("計算過程中有被除數為0的存在,計算表達式失敗!") value = float(part1) / float(part2) # 計算除法 #print("計算:%s=%s:" % (data,value) ) # 獲取第一個匹配到的乘除計算結果value,將value放回原表達式 s1, s2 = re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', expression, 1) # 分割表達式 #print("上一個表達式:",expression) next_expression = "%s%s%s" % (s1, value, s2) # 將計算結果替換會表達式 #print("下一個表達式%s" % next_expression) return chengchu(next_expression) # 遞歸表達式 def jiajian(expression): """ 加減運算 :param expression: 表達式 :return: 返回沒有加減的表達式/最終計算結果 """ expression = expression.replace('+-','-') # 替換表達式里的所有'+-' expression = expression.replace('--','+') # 替換表達式里的所有'--' expression = expression.replace('-+','-') # 替換表達式里的所有'-+' expression = expression.replace('++','+') # 替換表達式里的所有'++' #print("處理特殊加減后的表達式:",expression) data = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression) # 匹配加減號 if not data: # 如果不存在加減號,則證明表達式已計算完成,返回最終結果 return expression val = re.search('[\-]?\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression).group() if len(val.split('+')) > 1: # 以加號分割成功,有加法計算 part1, part2 = val.split('+') value = float(part1) + float(part2) # 計算加法 elif val.startswith('-'): # 如果是已'-'開頭則需要單獨計算 part1, part2, part3 = val.split('-') value = -float(part2) - float(part3) # 計算以負數開頭的減法 else: part1, part2 = val.split('-') value = float(part1) - float(part2) # 計算減法 s1, s2 = re.split('[\-]?\d+\.*\d*[\+\-]{1}\d+\.*\d*', expression, 1) # 分割表達式 #print("計算%s=%s" % (val,value)) next_expression = "%s%s%s" % (s1, value, s2) # 將計算后的結果替換回表達式,生成下一個表達式 #print("下一個表達式: ",next_expression) return jiajian(next_expression) # 遞歸運算表達式 def del_bracket(expression): """ 小括號去除運算 :param expression: 表達式 :return: """ if not re.search(r'\(([^()]+)\)',expression): # 判斷小括號,如果不存在小括號,直接調用乘除,加減計算 ret1 = chengchu(expression) ret2 = jiajian(ret1) return ret2 # 返回最終計算結果 data = re.search(r'\(([^()]+)\)', expression).group() # 如果有小括號,匹配出優先級最高的小括號 #print("獲取表達式",data) data = data.strip('[\(\)]') # 剔除小括號 ret1 = chengchu(data) # 計算乘除 #print("全部乘除計算完后的表達式:",ret1) ret2 = jiajian(ret1) # 計算加減 #print("全部加減計算結果:",ret2) part1, replace_str, part2 = re.split(r'\(([^()]+)\)', expression, 1) # 將小括號計算結果替換回表達式 expression = '%s%s%s' % (part1, ret2, part2) # 生成新的表達式 return del_bracket(expression) # 遞歸去小括號 if __name__ == "__main__": try: expression = welcome_func() # 獲取到的表達式 #expression = "-1+ 3 *(-3*2-2/-2+1)/2" #expression = '1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))' reslut = eval(expression) # 用eval計算驗證 ret = del_bracket(expression) # 用函數計算后得出的結果 reslut = float(reslut) ret = float(ret) if reslut == ret: # 將兩種方式計算的結果進行比較,如果相等,則計算正確,輸出結果 print("eval計算結果:%s" % reslut) print("表達式計算結果:%s" % ret) else: # 兩種計算方式的結果不正確,提示異常,並返回兩種方式的計算結果 print("計算結果異常,請重新檢查!") print("eval計算結果:%s" % reslut) print("表達式計算結果:%s" % ret) except(SyntaxError,ValueError,TypeError): # 如果有不合法輸出,則拋出錯誤 print("輸入表達式不合法,請重新檢查!")