欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器

 更新時(shí)間:2016年11月02日 09:35:13   投稿:daisy  
相信大家在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時(shí),就學(xué)習(xí)了簡(jiǎn)單四則運(yùn)算表達(dá)式求解的一個(gè)算法,可惜一直沒有自己動(dòng)手實(shí)現(xiàn)過這個(gè)算法。最近重拾數(shù)據(jù)結(jié)構(gòu)與算法,恰巧又正在用Python比較頻繁,所幸就用它來(lái)實(shí)現(xiàn)這個(gè)算法,雖然網(wǎng)上有很多代碼,不過作為一個(gè)學(xué)習(xí)者,還是應(yīng)當(dāng)親自動(dòng)手實(shí)現(xiàn)。

一、算法

     1、算法的主要思想就是將一個(gè)中綴表達(dá)式(Infix expression)轉(zhuǎn)換成便于處理的后綴表達(dá)式(Postfix expression),然后借助于棧這個(gè)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),計(jì)算出表達(dá)式的結(jié)果。

     2、關(guān)于如何講普通的表達(dá)式轉(zhuǎn)換成后綴表達(dá)式,以及如何處理后綴表達(dá)式并計(jì)算出結(jié)果的具體算法描述不在此敘述了,書上有詳細(xì)的說明。

二、簡(jiǎn)易計(jì)算器

使用說明

使用該計(jì)算器類的簡(jiǎn)單示例如下:

# usage
c = Calculator()
print('result: {:f}'.formart(c.get_result('1.11+2.22-3.33*4.44/5.55')))
# output:
result: 0.666000

測(cè)試案例

為了對(duì)這個(gè)計(jì)算器進(jìn)行有效地檢驗(yàn),設(shè)計(jì)了幾組測(cè)試案例,測(cè)試結(jié)果如下:

Test No.1: (1.11) = 1.110000
Test No.2: 1.11+2.22-3.33*4.44/5.55 = 0.666000
Test No.3: 1.11+(2.22-3.33)*4.44/5.55 = 0.222000
Test No.4: 1.11+(2.22-3.33)*(4.44+5.55)/6.66 = -0.555000
Test No.5: 1.11*((2.22-3.33)*(4.44+5.55))/(6.66+7.77) = -0.852992
Test No.6: (1.11+2.22)*(3.33+4.44)/5.55*6.66 = 31.048920
Test No.7: (1.11-2.22)/(3.33+4.44)/5.55*(6.66+7.77)/(8.88) = -0.041828
Test No.8: Error: (1.11+2.22)*(3.33+4.44: missing ")", please check your expression
Test No.9: Error: (1.11+2.22)*3.33/0+(34-45): divisor cannot be zero
Test No.10: Error: 12+89^7: invalid character: ^

實(shí)現(xiàn)代碼

棧的實(shí)現(xiàn)

棧實(shí)際上就是一個(gè)被限制操作的表,所有的操作只能在棧的頂端(入棧、出棧等),以下是使用Python代碼實(shí)現(xiàn)的簡(jiǎn)單的棧:

class Stack(object):
  """
  The structure of a Stack.
  The user don't have to know the definition.
  """
  def __init__(self):
    self.__container = list()
  def __is_empty(self):
    """
    Test if the stack is empty or not
    :return: True or False
    """
    return len(self.__container) == 0
  def push(self, element):
    """
    Add a new element to the stack
    :param element: the element you want to add
    :return: None
    """
    self.__container.append(element)
  def top(self):
    """
    Get the top element of the stack
    :return: top element
    """
    if self.__is_empty():
      return None
    return self.__container[-1]
  def pop(self):
    """
    Remove the top element of the stack
    :return: None or the top element of the stack
    """
    return None if self.__is_empty() else self.__container.pop()
  def clear(self):
    """
    We'll make an empty stack
    :return: self
    """
    self.__container.clear()
    return self

計(jì)算器類的實(shí)現(xiàn)

在計(jì)算器類中,我們將表達(dá)式的合法性驗(yàn)證單獨(dú)放在一個(gè)函數(shù)中完成,但是實(shí)際上如果需要,也可以直接放在中綴表達(dá)式轉(zhuǎn)后綴表達(dá)式的函數(shù)中實(shí)現(xiàn),這樣只需要一次遍歷表達(dá)式即可同時(shí)完成驗(yàn)證和轉(zhuǎn)換工作。但是為了保持結(jié)構(gòu)清晰,還是分開來(lái)實(shí)現(xiàn)比較好,每個(gè)函數(shù)盡可能最好一件事情才是比較實(shí)在的。

在該計(jì)算器類中,有很多種極端的情況沒有被考慮進(jìn)去,因?yàn)槟菢拥脑捳麄€(gè)實(shí)現(xiàn)的代碼會(huì)更多。不過,可以在后期為整個(gè)類繼續(xù)擴(kuò)展,添加新的功能也是可以的。目前實(shí)現(xiàn)的就是主要框架,包括基本的錯(cuò)誤檢測(cè)和運(yùn)算,重點(diǎn)時(shí)學(xué)習(xí)運(yùn)用棧這個(gè)看似簡(jiǎn)單卻強(qiáng)大的數(shù)據(jù)結(jié)構(gòu)解決問題。

class Calculator(object):
  """
  A simple calculator, just for fun
  """
  def __init__(self):
    self.__exp = ''
  def __validate(self):
    """
    We have to make sure the expression is legal.
    1. We only accept the `()` to specify the priority of a sub-expression. Notes: `[ {` and `] }` will be
    replaced by `(` and `)` respectively.
    2. Valid characters should be `+`, `-`, `*`, `/`, `(`, `)` and numbers(int, float)
    - Invalid expression examples, but we can only handle the 4th case. The implementation will
    be much more sophisticated if we want to handle all the possible cases.:
      1. `a+b-+c`
      2. `a+b+-`
      3. `a+(b+c`
      4. `a+(+b-)`
      5. etc
    :return: True or False
    """
    if not isinstance(self.__exp, str):
      print('Error: {}: expression should be a string'.format(self.__exp))
      return False
    # Save the non-space expression
    val_exp = ''
    s = Stack()
    for x in self.__exp:
      # We should ignore the space characters
      if x == ' ':
        continue
      if self.__is_bracket(x) or self.__is_digit(x) or self.__is_operators(x) \
          or x == '.':
        if x == '(':
          s.push(x)
        elif x == ')':
          s.pop()
        val_exp += x
      else:
        print('Error: {}: invalid character: {}'.format(self.__exp, x))
        return False
    if s.top():
      print('Error: {}: missing ")", please check your expression'.format(self.__exp))
      return False
    self.__exp = val_exp
    return True
  def __convert2postfix_exp(self):
    """
    Convert the infix expression to a postfix expression
    :return: the converted expression
    """
    # highest priority: ()
    # middle: * /
    # lowest: + -
    converted_exp = ''
    stk = Stack()
    for x in self.__exp:
      if self.__is_digit(x) or x == '.':
        converted_exp += x
      elif self.__is_operators(x):
        converted_exp += ' '
        tp = stk.top()
        if tp:
          if tp == '(':
            stk.push(x)
            continue
          x_pri = self.__get_priority(x)
          tp_pri = self.__get_priority(tp)
          if x_pri > tp_pri:
            stk.push(x)
          elif x_pri == tp_pri:
            converted_exp += stk.pop() + ' '
            stk.push(x)
          else:
            while stk.top():
              if self.__get_priority(stk.top()) != x_pri:
                converted_exp += stk.pop() + ' '
              else:
                break
            stk.push(x)
        else:
          stk.push(x)
      elif self.__is_bracket(x):
        converted_exp += ' '
        if x == '(':
          stk.push(x)
        else:
          while stk.top() and stk.top() != '(':
            converted_exp += stk.pop() + ' '
          stk.pop()
    # pop all the operators
    while stk.top():
      converted_exp += ' ' + stk.pop() + ' '
    return converted_exp
  def __get_result(self, operand_2, operand_1, operator):
    if operator == '+':
      return operand_1 + operand_2
    elif operator == '-':
      return operand_1 - operand_2
    elif operator == '*':
      return operand_1 * operand_2
    elif operator == '/':
      if operand_2 != 0:
        return operand_1 / operand_2
      else:
        print('Error: {}: divisor cannot be zero'.format(self.__exp))
        return None
  def __calc_postfix_exp(self, exp):
    """
    Get the result from a converted postfix expression
    e.g. 6 5 2 3 + 8 * + 3 + *
    :return: result
    """
    assert isinstance(exp, str)
    stk = Stack()
    exp_split = exp.strip().split()
    for x in exp_split:
      if self.__is_operators(x):
        # pop two top numbers in the stack
        r = self.__get_result(stk.pop(), stk.pop(), x)
        if r is None:
          return None
        else:
          stk.push(r)
      else:
        # push the converted number to the stack
        stk.push(float(x))
    return stk.pop()
  def __calc(self):
    """
    Try to get the result of the expression
    :return: None or result
    """
    # Validate
    if self.__validate():
      # Convert, then run the algorithm to get the result
      return self.__calc_postfix_exp(self.__convert2postfix_exp())
    else:
      return None
  def get_result(self, expression):
    """
    Get the result of an expression
    Suppose we have got a valid expression
    :return: None or result
    """
    self.__exp = expression.strip()
    return self.__calc()
  """
  Utilities
  """
  @staticmethod
  def __is_operators(x):
    return x in ['+', '-', '*', '/']
  @staticmethod
  def __is_bracket(x):
    return x in ['(', ')']
  @staticmethod
  def __is_digit(x):
    return x.isdigit()
  @staticmethod
  def __get_priority(op):
    if op in ['+', '-']:
      return 0
    elif op in ['*', '/']:
      return 1

總結(jié)

以上就是利用Python實(shí)現(xiàn)簡(jiǎn)單四則運(yùn)算計(jì)算器的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能有所幫助,如果有疑問大家可以留言交流。

參考

《數(shù)據(jù)結(jié)構(gòu)與算法(C語(yǔ)言)》上相關(guān)章節(jié)算法描述

相關(guān)文章

  • 初探Python元編程之理解并使用元編程改變代碼的代碼示例

    初探Python元編程之理解并使用元編程改變代碼的代碼示例

    在Python編程中,有一種強(qiáng)大的技術(shù)允許我們?cè)谶\(yùn)行時(shí)修改或生成代碼,這就是元編程,Python的元編程工具包括裝飾器,元類,以及函數(shù)和類的各種動(dòng)態(tài)修改技術(shù),這篇文章將向你介紹元編程的基本概念,并通過實(shí)例講解如何使用元編程
    2023-07-07
  • 簡(jiǎn)單解析Django框架中的表單驗(yàn)證

    簡(jiǎn)單解析Django框架中的表單驗(yàn)證

    這篇文章主要介紹了簡(jiǎn)單解析Django框架中的表單驗(yàn)證,Django是Python重多人氣框架中最為著名的一個(gè),需要的朋友可以參考下
    2015-07-07
  • pycharm 實(shí)現(xiàn)復(fù)制一行的快捷鍵

    pycharm 實(shí)現(xiàn)復(fù)制一行的快捷鍵

    這篇文章主要介紹了pycharm 實(shí)現(xiàn)復(fù)制一行的快捷鍵,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-01-01
  • Python通過樸素貝葉斯和LSTM分別實(shí)現(xiàn)新聞文本分類

    Python通過樸素貝葉斯和LSTM分別實(shí)現(xiàn)新聞文本分類

    樸素貝葉斯法(Naive Bayes model)是基于貝葉斯定理與特征條件獨(dú)立假設(shè)的分類方法。LSTM則是一種時(shí)間循環(huán)神經(jīng)網(wǎng)絡(luò),適合于處理和預(yù)測(cè)時(shí)間序列中間隔和延遲相對(duì)較長(zhǎng)的重要事件。本文將通過這兩個(gè)方法分別實(shí)現(xiàn)新聞文本分類,需要的可以參考一下
    2021-12-12
  • Python??序列化反序列化和異常處理的問題小結(jié)

    Python??序列化反序列化和異常處理的問題小結(jié)

    這篇文章主要介紹了Python?序列化反序列化和異常處理,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 使用PyCharm批量爬取小說的完整代碼

    使用PyCharm批量爬取小說的完整代碼

    這篇文章主要介紹了使用PyCharm批量爬取小說,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Python的Bottle框架中返回靜態(tài)文件和JSON對(duì)象的方法

    Python的Bottle框架中返回靜態(tài)文件和JSON對(duì)象的方法

    這篇文章主要介紹了Python的Bottle框架中返回靜態(tài)文件和JSON對(duì)象的方法,Bottle框架在Python開發(fā)者中具有很高的人氣,需要的朋友可以參考下
    2015-04-04
  • 徹底卸載Anaconda詳細(xì)教程(超詳細(xì)!)

    徹底卸載Anaconda詳細(xì)教程(超詳細(xì)!)

    這篇文章主要給大家介紹了關(guān)于徹底卸載Anaconda的相關(guān)資料,Anaconda(官方網(wǎng)站)就是可以便捷獲取包且對(duì)包能夠進(jìn)行管理,同時(shí)對(duì)環(huán)境可以統(tǒng)一管理的發(fā)行版本,需要的朋友可以參考下
    2023-11-11
  • Python中的response.text與content區(qū)別詳解

    Python中的response.text與content區(qū)別詳解

    這篇文章主要介紹了Python中的response.text與content區(qū)別詳解,?從網(wǎng)絡(luò)請(qǐng)求下來(lái)的數(shù)據(jù),他們都是字節(jié)類型的,如果服務(wù)器不指定的話,默認(rèn)編碼是"ISO-8859-1",我們使用text直接拿到的是字符串類型,沒有進(jìn)行解碼操作,則會(huì)出現(xiàn)亂碼問題,需要的朋友可以參考下
    2023-12-12
  • 聊聊pytorch測(cè)試的時(shí)候?yàn)楹我由蟤odel.eval()

    聊聊pytorch測(cè)試的時(shí)候?yàn)楹我由蟤odel.eval()

    這篇文章主要介紹了聊聊pytorch測(cè)試的時(shí)候?yàn)楹我由蟤odel.eval()的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05

最新評(píng)論