python之計算器操作(第四天)

来源:http://www.cnblogs.com/wushank/archive/2016/01/31/5172792.html
-Advertisement-
Play Games

作業: 使用正則表達式和遞歸實現計算器功能。 實現: 1、實現帶括弧的計算 2、實現指數、加減乘除求餘等功能 一、實例說明: 本實例自己寫了個版本,但依舊存在一點bug,例:-2-2等計算問題,故最後在武SIR的代碼基礎上加了指數、求餘等功能。 該計算器思路: 1、遞歸尋找表達式中只含有 數字和運算


作業:

     使用正則表達式和遞歸實現計算器功能。

 

 實現:

       1、實現帶括弧的計算

       2、實現指數、加減乘除求餘等功能

       

一、實例說明:

本實例自己寫了個版本,但依舊存在一點bug,例:-2-2等計算問題,故最後在武SIR的代碼基礎上加了指數、求餘等功能。

該計算器思路:
1、遞歸尋找表達式中只含有 數字和運算符的表達式,並計算結果
2、由於整數計算會忽略小數,所有的數字都認為是浮點型操作,以此來保留小數
使用技術:
1、正則表達式
2、遞歸

 

二、流程圖:

 

三、代碼:

#!/usr/bin/python27
#_*_ coding=utf-8 _*_

'''
Created on 2016年1月17日
@author: 王凱
'''


'''
該計算器思路:
    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,os,sys

def compute_exponent(arg):
    """ 操作指數
    :param expression:表達式
    :return:計算結果
    """

    val = arg[0]
    pattern = re.compile(r'\d+\.?\d*[\*]{2}[\+\-]?\d+\.?\d*')
    mch = pattern.search(val)
    if not mch:
        return
    content = pattern.search(val).group()

    if len(content.split('**'))>1:
        n1, n2 = content.split('**')
        value = float(n1) ** float(n2)
    else:
        pass

    before, after = pattern.split(val, 1)
    new_str = "%s%s%s" % (before,value,after)
    arg[0] = new_str
    compute_exponent(arg)

def compute_mul_div(arg):
    """ 操作乘除
    :param expression:表達式
    :return:計算結果
    """

    val = arg[0]
    pattern = re.compile(r'\d+\.?\d*[\*\/\%\/\/]+[\+\-]?\d+\.*\d*')
    mch = pattern.search(val)
    if not mch:
        return
    content = pattern.search(val).group()

    if len(content.split('*'))>1:
        n1, n2 = content.split('*')
        value = float(n1) * float(n2)
    elif len(content.split('//'))>1:
        n1, n2 = content.split('//')
        value = float(n1) // float(n2)
    elif len(content.split('%'))>1:
        n1, n2 = content.split('%')
        value = float(n1) % float(n2)
    elif len(content.split('/'))>1:
        n1, n2 = content.split('/')
        value = float(n1) / float(n2)
    else:
        pass

    before, after = pattern.split(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]

    pattern = re.compile(r'\d+\.?\d*[\+\-]{1}\d+\.?\d*')
    mch = pattern.search(val)
    if not mch:
        return
    content = pattern.search(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 = pattern.split(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_exponent(inp)

    # 處理表達式中的乘除求餘等
    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:最終計算結果
    """
    pattern = re.compile(r'\(([\+\-\*\/\%\/\/\*\*]*\d+\.*\d*){2,}\)')
    # 如果表達式中已經沒有括弧,則直接調用負責計算的函數,將表達式結果返回,如:2*1-82+444
    #if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', expression):
    if not pattern.search(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 = pattern.search(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 = pattern.split(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,'previous result is',"="*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__":
    flag = True

    os.system('clear')                                                     ###清屏###

    print('\n================================================================')
    print('\033[33m 歡迎使用計算器 :\033[0m')
    print('\n================================================================')



    while flag:
        calculate_input = raw_input('\033[32m請輸入計算的表達式 | (退出:q)\033[0m')
        calculate_input = re.sub('\s*','',calculate_input)
        if len(calculate_input) == 0:
            continue
        elif calculate_input == 'q':
            sys.exit('退出程式')
        elif re.search('[^0-9\.\-\+\*\/\%\/\/\*\*\(\)]',calculate_input):
            print('\033[31m 輸入錯誤,請重新輸入!!!\033[0m')
        else:
            result = exec_bracket(calculate_input)
            print('the expression result is %s' % result)
計算器

 

四、針對python2.7和python3.4無太大差別,故只需要一個版本即可。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 通過調用分頁存儲過程,實現數據源分頁。
  • 進程是存在獨立的記憶體和資源的,但是AppDomain僅僅是邏輯上的一種抽象。一個process可以存在多個AppDomain。各個AppDomain之間的數據時相互獨立的。一個線程可以穿梭多個AppDomain。 一、屬性 ActivationContext 獲取當前應用程式域的激活上下文。Appl
  • AppDomain是CLR(Common Language Runtime:公共語言運行庫),它可以載入Assembly、創建對象以及執行程式。 AppDomain是CLR實現代碼隔離的基本機制。 每一個AppDomain可以單獨運行、停止;每個AppDomain都有自己預設的異常處理;一個AppD
  • 現在做程式都要將動態的頁面轉換成靜態頁面,今天教大家在ASP.NET 中實現靜態頁面的生成方法。 using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Secur
  • HTTP請求工具類(功能:1、獲取網頁html;2、下載網路圖片;): using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System
  • 今年做的一個上位機工控WPF項目,做個小小的總結把,以後隨時來找 請不要帶血亂噴,我只是菜鳥.___by 鮑隊 類似於這樣子的;大致的意思是:一個代碼變數,通過改變變數的值,綁定這個變數的這個圓顏色也在變化 就是一種心跳效果 在網上數據觸發的感覺不多,廢了不少時間,這裡做個總結 1:通知 class
  • 許可權系統的組成通常包括RBAC模型、許可權驗證、許可權管理以及界面訪問控制。現有的一些許可權系統分析通常存在以下問題: (1)沒有許可權的設計思路 認為所有系統都可以使用一套基於Table設計的許可權系統。事實上設計許可權系統的重點是判斷角色的穩定性和找出最小授權需求。角色的穩定性決定了系統是通過角色判斷許可權還
  • 公司準備開發一套工作流引擎,以前沒有什麼OA開發經驗,也是第一次設計工作流引擎,我把我的一些思路分享一下,希望得到些幫助或者能幫助到一些人。 產品的定位: 1、能夠做到前後端分離 2、可以做到項目的分離使用,通過介面來實現 3、支持複雜流程邏輯 例如: 填寫加班表單-》多人審核=》退回=》填寫證明人
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...