Github項目地址: https://github.com/cliohl/calculatorpython
PSPgit
PSP2.1github |
personal Software Process Stagesapp |
預估時間(分鐘)dom |
實際耗時(分鐘)ide |
Planning函數 |
計劃工具 |
20性能 |
30單元測試 |
· Estimate |
· 估計這個任務須要多少時間 |
20 |
30 |
Development |
開發 |
190 |
268 |
· Analysis |
· 需求分析 (包括學習新技術) |
10 |
8 |
· Design Spec |
· 生成設計文檔 |
/ |
/ |
· Design Review |
· 設計複審 (和同事審覈設計文檔) |
/ |
/ |
· Coding Standard |
· 代碼規範 (爲目前的開發制定合適的規範) |
/ |
/ |
· Design |
· 具體設計 |
60 |
90 |
· Coding |
· 具體編碼 |
120 |
150 |
· Code Review |
· 代碼複審 |
/ |
/ |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
10 |
20 |
Reporting |
報告 |
80 |
60 |
· Test Report |
· 測試報告+博客 |
60 |
50 |
· Size Measurement |
· 計算工做量 |
/ |
/ |
· Postmortem & Process Improvement Plan |
· 過後總結, 並提出過程改進計劃 |
20 |
10 |
合計 |
|
300 |
358 |
題目描述:
(1)能自動生成小學四則運算題目,而且不能出現負數;
(2)能支持真分數的四則運算;
思路:
(1)四則運算加減乘除:因爲基礎不紮實,現只能實現兩個隨機正數的四則運算。
(2)因爲不能出現負數,在進行減法運算的時候,我用了2種不一樣的方法實現,一種是先隨機生成減數,而後在0到減數之間隨機生成被減數,這樣能夠控制被減數必定小於減數,第二種是隨機生成兩個數,而後比較大小,大的數做爲減數,小的數做爲被減數。
(3)在進行除法運算時,由於被除數不能爲零,因此在被除數的隨機取值範圍內不能包括0,在取隨機分數的時候,分母不能爲零,因此分母的隨機取值範圍也不包括0。
(4)在進行真分數運算的時候,導入python自帶的fractions庫。
(5)由於不包含假分數,因此在進行分數生成的時候也須要對分子和分母比較大小,大的數爲分子,小的數爲分母。
實現過程:
設計兩個函數:
def create1(q,ans) 生成整數四則運算
def create2(q,ans) 生成真分數四則運算
def createf() 生成兩個真分數
函數關係:
create1(q,ans)和create2(q,ans)均爲獨立的函數,負責生成四則運算。
主函數部分主要分爲2大部分,第一個爲測試部分,第二個爲練習部分。測試部分能夠自定義題目數量及測試類型,測試完畢給出測試的分數,而且能夠選擇是否查看答案。練習部分也能夠自定義題目數量及測試類型,每完成一提都會判斷結果對錯,若是錯誤會給出正確答案。
代碼說明:
詳細代碼以下所示:
1 def create1(q,ans)函數
1 def create1(q, ans): # 兩個整數的四則運算 2 symbol = random.choice(['+', '-', '*', '/']) # 生成隨機符號 3 if symbol == '+': 4 n1 = random.randint(0, 100) # 隨機生成0到100的整數 5 n2 = random.randint(0, 100) 6 q.append(str(n1) + ' + ' + str(n2)+' = ') 7 ans.append(n1 + n2) 8 elif symbol == '-': 9 n1 = random.randint(0, 100) # 隨機生成0到100的整數 10 n2 = random.randint(0, n1) 11 q.append(str(n1) + ' - ' + str(n2)+' = ') 12 ans.append(n1 - n2) 13 elif symbol == '*': 14 n1 = random.randint(0, 50) # 隨機生成0到100的整數 15 n2 = random.randint(0, 50) 16 q.append(str(n1) + ' × ' + str(n2)+' = ') 17 ans.append(n1 * n2) 18 else: 19 n1 = random.randint(0, 50) # 隨機生成0到100的整數 20 if n1 == 0: 21 n2 = random.randint(1, 50) 22 else: 23 n2 = random.randint(1, n1) 24 while n1 % n2 != 0: 25 n1 = random.randint(1, 50) 26 n2 = random.randint(1, n1) 27 q.append(str(n1) + ' ÷ ' + str(n2)+' = ') 28 ans.append(Fraction(n1, n2))
2 def createf()函數
1 def createf(): 2 # 生成2個分數 3 fz = random.randint(0, 20) 4 if fz == 0: 5 fm = random.randint(1, 20) 6 else: 7 fm = random.randint(fz,20) 8 f1 = Fraction(fz, fm) # 第一個分數 9 fz = random.randint(1, 20) 10 fm = random.randint(fz, 20) 11 f2 = Fraction(fz, fm) # 第二個分數 12 return f1, f2
3 def create2(q,ans)函數
1 def create2(q, ans): # 兩個分數的四則運算 2 symbol = random.choice(['+', '-', '*', '/']) # 生成隨機符號 3 f1, f2 = createf() 4 if symbol == '+': 5 while f1 + f2 > 1: 6 f1, f2 = createf() 7 q.append(str(f1) + ' + ' + str(f2)+' = ') 8 ans.append(f1 + f2) 9 elif symbol == '-': 10 f1, f2 = max(f1, f2), min(f1, f2) 11 q.append(str(f1) + ' - ' + str(f2)+' = ') 12 ans.append(f1 - f2) 13 elif symbol == '*': 14 while f1 * f2 > 1: 15 f1, f2 = createf() 16 q.append(str(f1) + ' × ' + str(f2)+' = ') 17 ans.append(f1 * f2) 18 else: 19 while Fraction(f1, f2) > 1: 20 f1, f2 = createf() 21 q.append(str(f1) + ' ÷ ' + str(f2)+' = ') 22 ans.append(Fraction(f1, f2))
4 主函數
1 while 1: 2 print("請輸入類型:一、測試 2 、練習 三、退出") 3 t = int(input()) 4 if t == 3: 5 break 6 elif t == 1: # 測試 7 print("請輸入你想要的四則運算:一、整數 二、分數 三、混合 4 、退出") 8 n = int(input()) 9 while n > 4: 10 print("選擇類型有誤!請從新選擇") 11 n = int(input()) 12 if n == 4: 13 break 14 print("請輸入你想要的題目數量(5的倍數):", end=' ') 15 qu = int(input()) 16 while qu % 5 != 0: 17 print("輸入數目有誤,請從新輸入!") 18 qu = int(input()) 19 pscore = 100 / qu 20 sscore = 0 21 ques = [] 22 ans = [] 23 if n == 1: # 整數測試題目 24 25 for i in range(qu): 26 create1(ques, ans) 27 elif n == 2: #分數測試題目 28 for i in range(qu): 29 create2(ques, ans) 30 elif n == 3: # 混合測試題目 31 for i in range(qu): 32 n = random.randint(0, 3) 33 if n == 0: 34 create2(ques, ans) 35 else: 36 create1(ques, ans) 37 for i in range(qu): 38 print("第{}題:{}".format(i + 1, ques[i]),end=' ') 39 a = input() 40 if a == str(ans[i]): 41 sscore = sscore + pscore 42 print("你所得分數爲:{}".format(sscore)) 43 print("是否查看正確答案? y/n", end=' ') 44 pan = input() 45 if pan == 'y': 46 for i in range(qu): 47 print(ques[i] + str(ans[i])) 48 elif t == 2: 49 print("請輸入你想要的四則運算:一、整數 二、分數 三、混合 四、退出") 50 n = int(input()) 51 while n > 4: 52 print("選擇類型有誤!請從新選擇") 53 n = int(input()) 54 if n == 4: 55 break 56 print("請輸入你想要的題目數量:") 57 qu = int(input()) 58 ques = [] 59 ans = [] 60 if n == 1: # 整數練習題目 61 for i in range(qu): 62 create1(ques, ans) 63 elif n == 2: # 分數練習題目 64 for i in range(qu): 65 create2(ques, ans) 66 elif n == 3: # 混合練習題目 67 for i in range(qu): 68 n = random.randint(0,3) 69 if n == 0: 70 create2(ques, ans) 71 else: 72 create1(ques, ans) 73 else: 74 print("選擇類型有誤!請從新選擇") 75 for i in range(qu): 76 print("第{}題:{}".format(i + 1, ques[i]),end=' ') 77 a = input() 78 if a == str(ans[i]): 79 print("回答正確!") 80 else: 81 print("回答錯誤!正確答案爲:{}".format(ans[i])) 82 else: 83 print("選擇類型有誤!請從新選擇")
測試運行:
單元測試:
測試create1(q,ans)函數,通過查找發現錯誤以下:
這裏我忽略了當n1爲0時的狀況,致使運行出錯。
改進以下:
問題解決。
測試create2(q,ans)函數,通過查找發現錯誤以下:
這裏我沒有考慮到當結果大於1成爲假分數的狀況,改進以下:
問題解決。
全體測試運行結果以下:
效能分析:
PyCharm提供了性能分析工具Run——Profile。
以下圖所示:
性能統計界面由Name、Call Count、Time(ms)、Own Time(ms) 4列組成一個表格,見下圖。
(表頭Name顯示被調用的模塊或者函數;Call Count顯示被調用的次數;Time(ms)顯示運行時間和時間百分比,時間單位爲毫秒(ms)。)
能夠看到,用戶輸入佔用了100%的時間,說明本代碼的絕大部分時間都是在等待用戶輸入。
如今來看看create1(q,ans)函數,create2(q,ans)函數,create1()函數的性能測試。以下圖所示:
能夠看到,生成整數題目調用了20次,生成分數調用了8次,生成分數題目調用了5次,所佔時間都爲0,說明函數調用佔比只佔了不多的一部分。
本代碼還有很大的改進空間,礙於能力與時間問題,就先不進行改進,往後有時間再修改代碼及分析。
我的感想:
看到這個題目以後的第一感受好像很簡單,但是真正動手去作才知道有不少細節是須要注意的。剛開始我是想作一個能夠自由控制多項式項數的,可以進行混合運算的四則運算器,但是後來發現有不少的小細節都卡住了思路,無奈之下只能先完成兩項的混合運算,等往後有空再鑽研混合運算及能夠添加括號的四則運算器。經過此次這個小項目,能夠發現本身許多的不足之處。原來作個項目是須要通過這麼多的步驟才能夠慢慢實現,經過閱讀構建之法的前3章,清楚的認識到本身的水平,往後還有待加油。但願明天的本身會比今天的本身更好。