基於遞歸和正則表達式實現的計算器,源碼如下:
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 該計算器思路: 1、遞歸尋找表達式中只含有 數字和運算符的表達式,並計算結果 2、由於整數計算會忽略小數,所有的數字都認為是浮點型操作,以此來保留小數 使用技術: 1、正則表達式 2、遞歸 執行流程如下: ******************** 請計算表達式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ******************** before: ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] -40.0/5=-8.0 after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] ========== 上一次計算結束 ========== before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] 9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953 after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))'] ========== 上一次計算結束 ========== before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))'] 60-30+-8.0*173545.880953=-1388337.04762 after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))'] ========== 上一次計算結束 ========== before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))'] -4*3=-12.0 after: ['1-2*(-1388337.04762--12.0/(16-3*2))'] ========== 上一次計算結束 ========== before: ['1-2*(-1388337.04762--12.0/(16-3*2))'] 16-3*2=10.0 after: ['1-2*(-1388337.04762--12.0/10.0)'] ========== 上一次計算結束 ========== before: ['1-2*(-1388337.04762--12.0/10.0)'] -1388337.04762--12.0/10.0=-1388335.84762 after: ['1-2*-1388335.84762'] ========== 上一次計算結束 ========== 我的計算結果: 2776672.69524 """ import re def compute_mul_div(arg): """ 操作乘除 :param expression:表達式 :return:計算結果 """ val = arg[0] mch = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val) if not mch: return content = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val).group() if len(content.split('*'))>1: n1, n2 = content.split('*') value = float(n1) * float(n2) else: n1, n2 = content.split('/') value = float(n1) / float(n2) before, after = re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val, 1) new_str = "%s%s%s" % (before,value,after) arg[0] = new_str compute_mul_div(arg) def compute_add_sub(arg): """ 操作加減 :param expression:表達式 :return:計算結果 """ while True: if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__("--"): arg[0] = arg[0].replace('+-','-') arg[0] = arg[0].replace('++','+') arg[0] = arg[0].replace('-+','-') arg[0] = arg[0].replace('--','+') else: break if arg[0].startswith('-'): arg[1] += 1 arg[0] = arg[0].replace('-','&') arg[0] = arg[0].replace('+','-') arg[0] = arg[0].replace('&','+') arg[0] = arg[0][1:] val = arg[0] mch = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val) if not mch: return content = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val).group() if len(content.split('+'))>1: n1, n2 = content.split('+') value = float(n1) + float(n2) else: n1, n2 = content.split('-') value = float(n1) - float(n2) before, after = re.split('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val, 1) new_str = "%s%s%s" % (before,value,after) arg[0] = new_str compute_add_sub(arg) def compute(expression): """ 操作加減乘除 :param expression:表達式 :return:計算結果 """ inp = [expression,0] # 處理表達式中的乘除 compute_mul_div(inp) # 處理 compute_add_sub(inp) if divmod(inp[1],2)[1] == 1: result = float(inp[0]) result = result * -1 else: result = float(inp[0]) return result def exec_bracket(expression): """ 遞歸處理括號,並計算 :param expression: 表達式 :return:最終計算結果 """ # 如果表達式中已經沒有括號,則直接調用負責計算的函數,將表達式結果返回,如:2*1-82+444 if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression): final = compute(expression) return final # 獲取 第一個 只含有 數字/小數 和 操作符 的括號 # 如: # ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] # 找出:(-40.0/5) content = re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression).group() # 分割表達式,即: # 將['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] # 分割更三部分:['1-2*((60-30+( (-40.0/5) *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] before, nothing, after = re.split('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression, 1) print 'before:',expression content = content[1:len(content)-1] # 計算,提取的表示 (-40.0/5),並活的結果,即:-40.0/5=-8.0 ret = compute(content) print '%s=%s' %( content, ret) # 將執行結果拼接,['1-2*((60-30+( -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] expression = "%s%s%s" %(before, ret, after) print 'after:',expression print "="*10,'上一次計算結束',"="*10 # 循環繼續下次括號處理操作,本次攜帶者的是已被處理后的表達式,即: # ['1-2*((60-30+ -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'] # 如此周而復始的操作,直到表達式中不再含有括號 return exec_bracket(expression) # 使用 __name__ 的目的: # 只有執行 python index.py 時,以下代碼才執行 # 如果其他人導入該模塊,以下代碼不執行 if __name__ == "__main__": #print '*'*20,"請計算表達式:", "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" ,'*'*20 #inpp = '1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ' inpp = "1-2*-30/-12*(-20+200*-3/-200*-300-100)" #inpp = "1-5*980.0" inpp = re.sub('\s*','',inpp) # 表達式保存在列表中 result = exec_bracket(inpp) print result