1. 程式人生 > >python 簡單計算器遞迴演算法 多層括號處理

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) ) # 等類似算式後,必須自己解析裡面的(),+,-,*,/符號和公式,利用遞迴演算法

拿到這個題目時,感覺無從下手。老師說利用開學來3天學習的知識是可以做出來的。然後我認真歸納總結前3天學習的基礎知識,經過3天3夜的奮戰終於給弄出來了。雖然中途也有想過放棄,但是沒有耕耘哪來的收穫。如果初學的同學想借鑑的話, 建議自己先仔細想想,如果實在無從下手可以參考下我的。特寫此文以自勉。程式中可能出現很多冗餘或bug,望勿見笑。下面我先說說我的思路。

  1. 先構造幾個函式方法用來進行最初的運算(加減乘除)
  2. 在運算函式中,先傳入一個字串,將字串利用正則表示式,findall函式生成可以取元素的列表形式,利用返回值,
  3. 先進行加法和減法運算,加減法能順利通過驗證,結果無誤
  4. 在算式中增加乘法和除法,用if語句進行判斷,如果有乘法和除法,需優先進行計算,通過驗證後
  5. 在算式中增加括號,增加括號後,需要進行for迴圈遍歷,如果遍歷的元素中包含括號,則優先處理計算括號裡面的
  6. 利用列表臨時儲存返回值,賦給原來的算式,進行遞迴,這樣算式越來越精簡。最終得出結果。

簡單流程圖如下:
計算器運算簡單流程圖

以下是實現程式碼:

#!/usr/bin/env python
#-*-coding:utf-8 -*-
import re # 定義函式 def add(x , y): #相加 return x + y def subtract(x, y): #相減 return x - y def multiply(x, y): #相乘 return x * y def divide(x, y): #相除 return x / y temp=[0] #定義一個臨時列表,並且賦值0,用來儲存結果 temp1=[] #定義一個臨時列表,用來臨時儲存列表 def sum2(ret): #定義一個函式用來進行資料的處理,運算 for index,mark in enumerate(ret): #遍歷列表,賦值給mark
if str(mark).count("(")==1 and str(mark).startswith("("): #如果mark中包含“(”並且以其開頭 ret.pop(index) #將該值(mark),在列表中移除 mark1=re.findall('^\(\-[0-9.]+|[0-9.]+|[*/+]|[-]',mark) #將mark元素,再次生成列表 h = float(re.sub('\(', '', mark1.pop(0))) #將該表的第一個元素取出,並且將其中所包含的括號替換移除 mark1.insert(0,h) #將重新得到的元素,重新插入列表中 sum2(mark1) #呼叫遞迴演算法,計算該列表 ret.insert(index,temp[-1]) #將臨時儲存資料的列表的最後一個元素,插入當前迴圈的索引位置 elif str(mark).count("(") >= 1: #如果mark元素中的括號熟練大於等於1 mark2 = re.findall('\([^()]+\)', mark) #將mark 元素去除最外層括號 t2=mark2[0] mark3 = re.findall('\((.+)\)', mark2[0]) #將mark 元素去除最外層括號 r1=re.findall('^\(\-[0-9.]+|[0-9.]+|[*/+]|[-]', mark2[0]) #將mark2生成可以計算的列表形式 h = float(re.sub('\(', '', r1.pop(0))) #如果r1 包含括號減號則將括號移除 r1.insert(0, h) r2=re.findall('^\(\-[0-9.]+|[0-9.]+|[*/+]|[-]', mark3[0]) #將mark3生成可以計算的列表形式 mark4=r1 if str(t2).count("(-")==1 else r2 #進行三目運算,判斷mark2(t2)是否包含括號,不同的值賦給mark4 temp1.clear() #如果臨時儲存temp1中有資料,則清空 temp1.extend(ret) #算式賦值給臨時儲存temp1 sum2(mark4) #呼叫遞迴演算法,計算該列表 q4 = mark.replace(str(mark2[0]), str(temp[-1])) #將結果值替換該運算位置,賦值給q4 if str(q4).count("(") >= 1: #如果字串q4中,包含括號的數量大於等於1 ret.pop(index) #將索引位置移除 ret.insert(index,q4) #將新得到的字q4 sum2(ret) #呼叫遞迴演算法,計算該列表 else: #如果不存在括號 ret.pop(index) #將索引位置移除 rr = re.findall('[0-9.]+|[*+\-/]+|\([^()]+\)+|\(.+\)+', q4) #採用正則重新生成可以可以計算列表形式 for index11, wor in enumerate(rr): #迴圈列印 rr中的元素 if len(wor) == 2 and wor in "+-*/": #如果元素wor的長度等於2 並且包含於 符號 "+-*/",就是同時出現兩個運算子號,其中有一個減號 rr.pop(index11) #移除該索引的元素 rr.insert(index11, wor[0]) #將wor元素的第一個運算子插入原來的位置 rrr = rr.pop(index11 + 1) #將下一個索引元素移除 rr.insert(index11 + 1, wor[1] + rrr) #將wor元素的第二個運算子與當前索引的下一個元素合併 sum2(rr) #呼叫遞迴演算法,計算該列表 q4=temp[-1] #將結果值賦值給q4,就是更新q4 (這裡經過計算後,q4 是一個數字了) ret.insert(index,q4) # 將q4 插入到當前運算式的位置 if len(ret)==3: #如果運算式的長度為3, 說明可以進行運算 sum2(ret) #呼叫遞迴演算法,計算該列表 elif ret[0]=="-": #如果運算式的第一個字元為減號,則跳過 pass elif len(ret)>=3 and q4.isalnum()==False: #如果運算式的長度等於大於3 並且包含非數字(包含運算子) q5=re.findall("[[0-9.]+|[+\-*/]",q4) #將q4 生成可以計算的列表形式 sum2(q5) #呼叫遞迴演算法,計算該列表 ret.pop(index) #將當前索引元素移除 ret.insert(index,temp[-1]) #將計算出的結果值插入當前位置 if len(ret)>=3: #如果算式的長度還大於等於3 sum2(ret) #則繼續遞迴 #elif mark == "*" or mark=="/": elif str(mark) in "*/": #如果字串元素中包含運算子 */乘法 和除法 if (len(ret))>=3: #如果算式長度大於等於3 x=float(ret.pop(index-1)) #取出一個元素並移除,轉化為浮點型 i=ret.pop(index-1) #取出一個元素並移除 這個是 運算子 y=ret.pop(index-1) #取出一個元素並移除,轉化為浮點型 y11=y #將y賦值給y11 if "(" in str(y): y12 = re.findall('\([^()]+\)', y11) #說明該元素中還包含括號,需要繼續運算 for index12, gg in enumerate(y12): #遍歷該元素 t2 = y12[0] r1 = re.findall('^\(\-[0-9.]+|[0-9.]+|[*/+]|[-]', y12[0]) y14 = re.findall('\((.+)\)', y12[0]) h = float(re.sub('\(', '', r1.pop(0))) r1.insert(0, h) r2 = re.findall('^\(\-[0-9.]+|[0-9.]+|[*/+]|[-]', y14[0]) # mark4 = str(t2).count("(-")==1 ? r1:r2 y13 = r1 if str(t2).count("(-") == 1 else r2 #三目運算 sum2(y13) y11 = y11.replace(str(y12[0]), str(temp[-1])) y12.pop(0) y12.append(temp[-1]) y15 = re.findall('[0-9.]+|[*+/]|\([^()]+\)+|\(.+\)+|[\-]', y11) sum2(y15) y=temp[-1] #將最終結果數字賦給y y=float(y) #轉化為浮點型 if str(mark)=="*": #如果元素mark 包含乘號 * s=multiply(x,y) #呼叫乘法計算公式 ret.insert(index-1,s) #將結果插入當前索引算式的位置 temp.append(s) #將乘積儲存在臨時列表中 if len(ret)>=3: #如果算式列表的長度還大於等於3 sum2(ret) #呼叫遞迴演算法,計算該列表 if str(mark) == "/": #如果元素mark 包含除號 / s=divide(x,y) temp.append(s) ret.insert(index - 1, s) if len(ret)>=3: sum2(ret) if len(ret)>=3: #如果算式列表的長度還大於等於3 x=ret.pop(0) #取出移除第一個元素 w2 = re.findall('[0-9.]+|[+\-*/]', str(x)) #將該元素生成可以計算的列表形式 if str(x)=="-": #如果x中包含 -號 x=str(x)+str(ret.pop(0)) #將當前和下一個元素合併 (形成負數) if len(w2) >= 4: #如果x中包含多個算式 sum2(w2) #呼叫遞迴演算法,計算該列表 x = temp[-1] #將計算的結果賦給x x=float(x) i=ret.pop(0) y=ret.pop(0) if str(y)=="-": y=y+str(ret.pop(0)) y =float(y) if i in "*/()": return else: if i in "+": #如果i包含 加號+ s = add(x, y) temp.append(s) elif i in "-": #如果i包含 加號- s= subtract(x,y) temp.append(s) s=temp[-1] #將得出的結果賦給s if len(ret) >= 2: #算式的長度大於等於2,說明還要繼續計算 ret.insert(0,s) #將該結果插入到算式中 sum2(ret) return temp[-2] #將臨時數值列表中的 最後一個值返回,該值就是最終結果 def sum(): arg = input("請輸入算式(只能包含數值,小括號,+-*/):") #輸入提示 print("您輸入的算式為:", arg) arg = re.sub('\s', '', arg) #將空格全部替換 arg1= re.match('[(\).+\-*/0-9]+$', arg) #判斷輸入的是否符合要求 if arg1: #如果符合要求,則執行下一步 #print(arg1.group()) pass else: #如果不符合,重試進入程式 print("您輸入的包含非法字元,請重新輸入!") arg="" sum() if str(arg).count("(")!=str(arg).count(")"): #如果輸入的括號對 數量不對,重新輸入 print("您輸入的括號對數有誤,請重新輸入!") arg = "" sum() arg2="'"+arg+"'" #print("計算機結果為:",eval(arg2)) ret=re.findall('\(.*\)|[0-9.]+|[*/+]|[-]',arg) #將字串初始成可以計算的列表形式 j=sum2(ret) #呼叫函式 return j x1 = sum() #呼叫函式 print("結果:", x1)

完畢!

相關推薦

python 簡單計算器演算法 括號處理

用python編寫一個簡單計算器 計算器開發需求 實現加減乘除及拓號優先順序解析 使用者輸入 # 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (

Python實現巢狀dict遍歷例項--三級選單/多級選單功能

要求:構建一個三(N)級選單,實現使用者可以根據指示選擇進入選單,退出選單,返回上層選單功能。知識點:dict資料的遍歷方法,遞迴遍歷方法。環境:Python3.6實現程式碼:#!/usr/bin/evn python # -*-coding:utf8 -*- class m

資料庫資料運用演算法生成樹形資料

第一步:準備表結構及對應的表資料1.表結構create table City(id char(32) not null,name varchar2(30),parent_id char(32) //父級欄位)2.插入資料insert into City (id, name,

Python漢諾塔問題演算法與程式

漢諾塔問題: 問題來源:漢諾塔來源於印度傳說的一個故事,上帝創造世界時作了三根金剛石柱子,在一根柱子上從上往下從小到大順序摞著64片黃金圓盤。上帝命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一回只能移動一個圓盤,只能移動在最頂端的圓盤。有預言說

樹的前、中、後序遍歷演算法與非)、序遍歷

二叉樹層次遍歷 非遞迴 void LevelOrder(Tree* T) { if(T == nullptr) return ; queue<Tree *> myqueue; myqueue.push(T); while(!myqueu

Python演算法

用python寫出一個漢諾塔遞迴函式 def move(n, a, b, c): if(n == 1): print(a,"->",c) return move(n-1, a, c, b) move(1, a, b, c) m

python簡單

首先要先理解什麼是遞迴? 在函式內部,可以呼叫其他函式。如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式。 下面講了一個很簡單的遞迴函式 def clac(n): print(n) if int(n/2) >0: return clac

資料結構實驗-C語言-二叉樹的建立,前、中、後序遍歷的遞迴演算法和非遞迴演算法,求葉子結點數目,求二叉樹深度,判斷二叉樹是否相似,求二叉樹左右子樹互換,二叉樹序遍歷的演算法,判斷二叉樹是否是完全二叉樹

1.實驗目的 熟練掌握二叉樹的二叉連結串列儲存結構的C語言實現。掌握二叉樹的基本操作-前序、中序、後序遍歷二叉樹的三種方法。瞭解非遞迴遍歷過程中“棧”的作用和狀態,而且能靈活運用遍歷演算法實現二叉樹的其它操作。 2.實驗內容 (1)二叉樹的二叉連結串列的建立 (2)二叉樹的前、中、後

python演算法演算法

# -*- coding: utf-8 -*- import numpy as np # 遞迴演算法 i = 0 def my_Recursion(list, n): global i try: if list[i] == n:

演算法簡單例項

一、什麼是遞迴  (遞迴 百度百科)     程式呼叫自身的程式設計技巧稱為遞迴(recursion)。它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的程式就可描述出解題過程所需要的多次重複計算。 二、如何使用遞迴解決問題

Python解決漢諾塔(演算法

        move(1,a,b,c)                      把柱子a上最後1個盤子移到柱子c上        move(n-1,b,a,c)                   把柱子b上的n-1個盤子通過柱子a移動到柱子c上print move(4, 'A', 'B', 'C')

漢諾塔 經典演算法 in python

   遞迴演算法,把大規模問題分解成容易解決而且求解方法相同的子問題,一般用遞迴函式實現,遞迴函式就是不斷呼叫自身的函式。    舉個例子:                  俄羅斯套娃(應該都玩過,裡面最小的那個不能開啟,其他能開啟。從最小的娃娃開始,用稍大的那個娃娃套

典型演算法例子-------Python實現

#!/usr/bin/python #coding=utf-8 ''' Created on 2012-9-25 @author: linzuxin ''' status = {} def factorial(n): ''' 輸入一

使用Python list通過實現一個表示式計算器

因為python list可以同時儲存不同的資料, 並且提供豐富的操作方案, 想想可以同時把數字和運算子號都儲存到列表中, 於是就誕生了使用列表寫個表示式計算器, 思路就是同時將數字和運算子儲存到列表, 然後從左向右計算所有乘除號兩邊的數值, 然後刪除兩個運算元

java演算法示例,單引數,引數

這兩天公司來了個新同事,順便帶一下,給他解釋下遞迴。 要點:找出口,出口即呼叫自己直到不能呼叫為止,不能呼叫即自身方法已經return到具體值。 例: package test; public class Test1 { /** * 題目:1-n相加 * @p

演算法(求n的加法組合,將一個整數拆分成個整數相加的形式, O(N)時間,O(N)空間)

網上的多種解法比較複雜,本文用遞迴方法,22行程式碼搞定。時間和空間複雜度已經降到最低! 第三版:加入創作思路。 這個函式的主要功能就是輸出所有組合。既然是輸出所有的組合,那就意味著內部有一個遍歷所有組合的過程。既然是遍歷,而且是O(N)時間,那就說明這個遍歷是按照某種輸出次序,從“第一個組合”遍歷到

Java實現八皇后問題,用陣列演算法簡單易懂

八皇后問題 要將八個皇后放在棋盤上,任何兩個皇后都不能互相攻擊。即沒有兩個皇后是在同一行、同一列或者同一對角上。 典型的八皇后問題,使用Java寫的演算法,演算法雖比較簡單,但難免會有新手會犯疏漏和錯誤,希望大家可以批評指正,共同交流進步! 程式碼

python入門之

表現形式:   函式體裡包含執行本身 def f1(): r = f1() f1()   例項:   斐波那契數   (a1+a2=a3   a2+a3=a4   a3+a4=a5   ......) def f1(a1,a2):

二叉樹遍歷之演算法

作者:石鍋拌飯  原文連結 二叉樹的遍歷演算法有多種,典型的有先序遍歷、中序遍歷、後序遍歷以及層序遍歷。而且這些遍歷的遞迴演算法較為簡單,程式碼很少,容易實現,本文就是彙總二叉樹遍歷的遞迴演算法,非遞迴演算法將在下一篇文章中進行總結。本文中用到的二叉樹例項如下: