歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

Python學(xué)習(xí)之正則表達(dá)式實(shí)現(xiàn)計(jì)算器算法詳解

發(fā)布時(shí)間:2018-05-04 14:58  回復(fù):0  查看:2925   最后回復(fù):2018-05-04 14:58  
正則表達(dá)式是python開(kāi)發(fā)中最常用的內(nèi)容之一,本文和大家分享的是python開(kāi)發(fā)中使用正則表達(dá)式實(shí)現(xiàn)計(jì)算器算法相關(guān)內(nèi)容,一起來(lái)看看吧,希望對(duì)大家 學(xué)習(xí)python 有所幫助。
 ?。?)不使用eval()等系統(tǒng)自帶的計(jì)算方法
  (2)實(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á)式開(kāi)頭有負(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á)式開(kāi)頭、負(fù)數(shù)前面存在減法、乘除式中存在負(fù)數(shù)且不在表達(dá)式開(kāi)頭。
  (1)當(dāng)負(fù)數(shù)出現(xiàn)在表達(dá)式開(kāi)頭:在前面加上一個(gè)0
 ?。?)負(fù)數(shù)前面存在減法:每次完成一次運(yùn)算后需要進(jìn)行一次符號(hào)檢查替換
 ?。?)乘除式中存在負(fù)數(shù)且不在表達(dá)式開(kāi)頭:將負(fù)號(hào)移到表達(dá)式最開(kāi)頭
  #!/usr/bin/env python# -*- coding:utf-8 -*-# Author Python學(xué)習(xí)之正則表達(dá)式實(shí)現(xiàn)計(jì)算器算法詳解 ang
  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á)式開(kāi)頭的情形
  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)在開(kāi)頭的問(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.開(kāi)頭位置負(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)換!?。?/span>
  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))


來(lái)源:網(wǎng)絡(luò)
您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?