首頁  >  文章  >  後端開發  >  Python設計計算器功能實現的完整實例分享

Python設計計算器功能實現的完整實例分享

黄舟
黄舟原創
2017-08-20 10:53:123794瀏覽

這篇文章主要介紹了Python設計實現的計算器功能,結合完整實例形式分析了Python3.5實現計算器功能的正則、字符串及數值運算等相關操作技巧,需要的朋友可以參考下

本文實例講述了Python設計實現的計算器功能。分享給大家供大家參考,具體如下:

透過利用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、正規處理使用者輸入的字串,然後對其進行判斷,判斷計算公式是否有括號,有就先將計算公式進行正則處理,先獲取最裡層的每一個數據,然後一一計算

所要用到的正規是:


inner = re.search("\([^()]*\)", calc_input)

2、把有括號的計算公式計算出來的結果取代原來初始公式的位置,計算先前分別對重複運算子進行處理

需要處理的重複運算的函數是


def del_double(str):
  str = str.replace("++", "+")
  str = str.replace("--", "-")
  str = str.replace("+-","-")
  str = str.replace("- -","-")
  str = str.replace("+ +","+")
  return str

3、然後依序從裡到外去除括號並進行計算,和位置替換


calc_input = calc_input.replace(inner.group(), str(ret))

將計算出來的結果分別替換原計算公式

4、最後得出沒有括號的公式,合併呼叫計算控制函數進行計算,中間需要注意的就是負號和數字與*在一起的處理,其它還算可以。

具體邏輯思路圖是:

以下是完整的程式碼:


#!/usr/bin/env python3.5
# -*-coding:utf8-*-
import re
a =r'1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ))- (-4*3)/(16-3*2))'
# */运算函数
def shengchu(str):
  calc = re.split("[*/]",str)   #用*/分割公式
  OP = re.findall("[*/]",str)  #找出所有*和/号
  ret = None
  for index,i in enumerate(calc):
    if ret:
      if OP[index-1] == "*":
        ret *= float(i)
      elif OP[index-1] == "/":
        ret /= float(i)
    else:
      ret = float(i)
  return ret
# 去掉重复运算,和处理特列+-符号
def del_double(str):
  str = str.replace("++", "+")
  str = str.replace("--", "-")
  str = str.replace("+-","-")
  str = str.replace("- -","-")
  str = str.replace("+ +","+")
  return str
# 计算主控制函数
def calc_contrl(str):
  tag = False
  str = str.strip("()") # 去掉最外面的括号
  str = del_double(str) # 调用函数处理重复运算
  find_ = re.findall("[+-]",str) # 获取所有+- 操作符
  split_ = re.split("[+-]",str) #正则处理 以+-操作符进行分割,分割后 只剩*/运算符
  if len(split_[0].strip()) == 0: # 特殊处理
    split_[1] = find_[0] + split_[1] # 处理第一个数字前有“-”的情况,得到新的带符号的数字
    # 处理第一个数字前为负数“-",时的情况,可能后面的操作符为“-”则进行标记
    if len(split_) == 3 and len(find_) ==2:
      tag =True
      del split_[0] # 删除原分割数字
      del find_[0]
    else:
      del split_[0] # 删除原分割数字
      del find_[0] # 删除原分割运算符
  for index, i in enumerate(split_):
    # 去除以*或/结尾的运算数字
    if i.endswith("* ") or i.endswith("/ "):
      split_[index] = split_[index] + find_[index] + split_[index+1]
      del split_[index+1]
      del find_[index]
  for index, i in enumerate(split_):
    if re.search("[*/]",i): # 先计算含*/的公式
      sub_res = shengchu(i) #调用剩除函数
      split_[index] = sub_res
  # 再计算加减
  res = None
  for index, i in enumerate(split_):
    if res:
      if find_[index-1] == "+":
        res += float(i)
      elif find_[index-1] == "-":
        # 如果是两个负数相减则将其相加,否则相减
        if tag == True:
          res += float(i)
        else:
          res -= float(i)
    else:
      # 处理没有括号时会出现i 为空的情况
      if i != "":
        res = float(i)
  return res
if __name__ == '__main__':
  calc_input = input("请输入计算公式,默认为:%s:" %a).strip()
  try:
    if len(calc_input) ==0:
      calc_input = a
    calc_input = r'%s'%calc_input # 做特殊处理,保持字符原形
    flag = True  # 初始化标志位
    result = None  # 初始化计算结果
    # 循环处理去括号
    while flag:
      inner = re.search("\([^()]*\)", calc_input)# 先获取最里层括号内的单一内容
      #print(inner.group())
      # 有括号时计算
      if inner:
        ret = calc_contrl(inner.group()) # 调用计算控制函数
        calc_input = calc_input.replace(inner.group(), str(ret)) # 将运算结果,替换原处理索引值处对应的字符串
        print("处理括号内的运算[%s]结果是:%s" % (inner.group(),str(ret)))
        #flag = True
      # 没有括号时计算
      else:
        ret = calc_contrl(calc_input)
        print("最终计算结果为:%s"% ret)
        #结束计算标志
        flag = False
  except:
    print("你输入的公式有误请重新输入!")

補充:

PYTHON正規表示式一覽:

模式 描述
#^ 符合字串的開頭
#$ 符合字串的結尾。
. 符合任意字符,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字符。
[...] 用來表示一組字元,單獨列出:[amk] 匹配'a','m'或'k
[^...] 不在[]中的字元:[^abc] 符合除了a,b,c之外的字元。
re* 符合0個或多個的表達式。
re+ 符合1個或多個的表達式。
re? 符合0個或1個由前面的正規表示式定義的片段,非貪婪方式
re{ n}
re{ n,} 精確地符合n個前面表達式。
re{ n, m} 符合n 到m 次由前面的正規表示式定義的片段,貪婪方式
a| b 符合a或b
(re) G符合括號內的表達式,也表示一個群組
(?imx) 正規表示式包含三種可選標誌:i, m, 或x 。只影響括號中的區域。
(?-imx) 正規表示式關閉 i, m, 或 x 可選標誌。只影響括號中的區域。
(?: re) 類似(...), 但不表示一個群組
(?imx : re) 在括號中使用i, m, 或x 可選標誌
#(?-imx: re) 在括號中不使用i, m, 或x 可選標誌
(?#...) #註解.
(?= re) 前向肯定界定符。如果所含正規表示式,以 ... 表示,在目前位置成功匹配時成功,否則失敗。但一旦所含表達式已經嘗試,匹配引擎根本沒有提高;模式的剩餘部分還要嘗試界定符的右邊。
(?! re) 前向否定界定符。與肯定界定符相反;當所含表達式不能在字串當前位置匹配時成功
#(?> re) 匹配的獨立模式,省去回溯。
\w 符合字母數字
#\W 符合非字母數字
\s 符合任意空白字符,等價於[\t\n\r\f].
\S 符合任意非空白字元
\d 符合任意數字,等價於[0-9].
#\D 符合任意非數字
\A 符合字串開始
\Z 符合字串結束,如果是存在換行,只符合到換行前的結束字串。 c
\z 符合字串結束
#\G 符合最後符合完成的位置。
\b 符合一個單字邊界,也就是指單字和空格間的位置。例如, 'er\b' 可以符合"never" 中的 'er',但不能符合 "verb" 中的 'er'。
\B 符合非單字邊界。 'er\B' 能符合 "verb" 中的 'er',但不能符合 "never" 中的 'er'。
\n, \t, etc.. 符合一個換行符號。匹配一個製表符。等等
\1...\9 匹配第n個分組的子表達式。
\10 符合第n個分組的子表達式,如果它經過符合。否則指的是八進位碼的表達式。

以上是Python設計計算器功能實現的完整實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn