結對編程
軟件工程 | 網工1934 |
---|---|
作業要求 | 作業要求 |
作業目標 | 實現一個自動生成小學四則運算題目的命令行程序 |
陳卓鴻 3119005320
張栩 3119005350
Github項目鏈接
一. PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | ||
- Estimate | 估計這個任務需要多少時間 | 970 | 1100 |
Development | 開發 | ||
- Analysis | 需求分析(包括學習新技術) | 100 | 100 |
- Design Spec | 生成設計文檔 | 40 | 50 |
- Desgin Review | 設計復審 | 30 | 30 |
- Coding Standard | 代碼規范(為目前的開發指定合適的規范) | 60 | 80 |
- Desgin | 具體設計 | 50 | 100 |
- Coding | 具體編碼 | 300 | 300 |
- Code Review | 代碼復審 | 60 | 60 |
- Test | 測試(自我測試,修改代碼,提交修改) | 200 | 300 |
Reporting | 報告 | ||
- Test Repor | 測試報告 | 50 | 50 |
- Size Measurement | 計算工作量 | 20 | 20 |
- Postmortem & Process Improvement Plan | 事后總結,並提出過程改進計划 | 60 | 60 |
總結 | 970 | 1100 |
二. 需求分析
類名 | 功能 |
---|---|
EquationHandler | 主啟動類 |
Equation | 四則運算的基本算式類 |
EquationUtils | 算式的處理工具類,包括生成算式和檢查 |
ElementUtils | 算式中的元素判斷和處理類,元素包括運算數和運算符等 |
CalculateUtils | 算式計算類,包括對算式轉換為逆波蘭式和別的四則運算 |
AccessUtils | 文件存取類,負責讀寫文件 |
RandomUtils | 隨機數生成器類,生成隨機運算數和運算符 |
三. 效能分析
耗時1
耗時2
耗內存1
耗內存2
四. 設計說明
1.算式實體類Equation
Java中String作為不可變對象,不方便處理,因此:
- Equation中使用
ArrayList<String>
作為底層存儲方式,運算數和運算符以String存放在其中 - 需要將Equation轉換為String時,依次獲取list中的元素通過StringBuilder生成字符串即可
2.減法檢查方法checkMinus
該項目減法檢查為生成算式后對算式進行處理,而不是在生成的過程中檢查
- 減法可能出現的情況
設a,b為運算數,(...)為子算式
-
a-b
如2/3 - 4
-
a-(...)
如1-(4/5-3)
-
(...)-b
如(1/3-1)-2
-
(...)-(...)
如(1-2)-(3-4)
- 對輸入的算式從左到右進行查找減號
- 獲取減號兩邊的運算數,記錄左運算數和右運算數的下標(此時該減法為子算式)
- 對運算數進行比較(不進行計算),若左運算數小於右運算數,則調換兩數位置
- 若右運算數是一個復雜的子算式,則將右運算數作為本方法的參數,遞歸進行減法檢查,檢查完后計算結果(此時右運算數的結果一定大於0)並返回,左運算數再與結果進行比較
- 若結果小於0,則通過處理第二步的下標,將處理后的子算式替換原下標的子算式;若結果大於0,則原來位置的子算式不改變
- 補充
由於算式從左到右檢查,左運算數實際已經檢查過,因此第4步不必檢查左運算數
獲取減號兩邊的運算數
同位置上, +
和-
可替換,×
和÷
可替換
- 減號左邊的運算數情況
a-b
運算數為a
a×(b+c)-d
運算數為a×(b+c)
(a+b)×c-d
運算數為(a+b)×c
3.計算模塊
生成的算式為中綴表達式,由於我們的實現思路需要將運算數和運算符存入List中,如果存入中綴表達式的話並不方便計算,而將中綴表達式轉換為后綴表達式(即逆波蘭式)以后能有效地簡化計算問題,而且也方便生成題目時查重的判斷。
- 逆波蘭表示法是波蘭邏輯學家J・盧卡西維茲(J・ Lukasewicz)於1929年首先提出的一種表達式的表示方法。后來,人們就把用這種表示法寫出的表達式稱作“逆波蘭表達式”。逆波蘭表達式把運算量寫在前面,把算符寫在后面。例如:[1, 2, 3, +, -,它等價於1-(2+3)。]
參考資料和實現方法:
分數處理
由於運算數以String的形式存儲,因此我們判斷是否為分數只需要判斷字符串中是否存在帶分數符號" ' "
和分數符號" / "
,如1'2/3
和4/5
都是分數類型
注:若計算時輸入的字符串為負數,類似-3
,會識別為分數類型,但是在轉換分數時會拋出異常,因為該字符串中不存在帶分數符號
和分數符號
負數處理和無窮大處理
若計算中出現負數,假設有某種減法情況沒有處理
導致結果出現負數,或者計算過程中出現了分母為0的分數(除數為0的除法)
導致結果會無窮大,則計算方法Calculate不會再往下執行,而是立即返回字符串"NaN"
若外層方法檢查到Calculate方法返回"NaN"
,會循環重新生成算式,直至結果不再為"NaN"
,然后將新生成的算式替代原算式
題目查重
經過逆波蘭式處理后,我們將得到的后綴表達式中的運算數和運算符按序存入List中。按照題目的要求,對於重復的題目的定義是完全相同的運算數、運算符、和運算順序。而根據逆波蘭式的性質,運算符的先后順序正好是從左往右的。故我們可以對存放題目的List進行遍歷,發現首個運算符后,存儲這個運算符,並取該運算符前的兩個運算數進行比對,如果是重復的,則遞歸調用該方法,直到所有運算符都檢查完畢。
五. 代碼實現
六. 運行實例和測試
生成一萬道算式
判斷運算數是否為整數測試
除法測試
查重測試
七. 項目小結
陳卓鴻:通過本次合作編程,我了解到自己在開發上有很多不足,對git和github的使用還需要多加學習,尤其是最后的merge非常糟糕,而且在項目管理上還是會出現混亂,比如不同git版本之間的切換和復原。在本次和同學共同開發過程中,我深刻體會到編程中交流的重要性,有效率的交流會提高項目完成的速度。
張栩:首先這次結對作業是我為數不多的和同學合作開發的經歷,比起平時獨立思考的作業,合作開發更多的是需要我和搭檔之間的配合與交流,比如這次作業中我和我的搭檔首先商量好了大致的思路和數據結構,由我的搭檔首先建立項目,而后我在GitHub上Fork之后進行一些方法的擴充,完善和測試。雖然在項目中遇到了比想象之中多得多的問題和異常,但因為合作開發,我們對對方的代碼都有比較深入的了解,所以在探討交流下都一一解決了,我認為結對編程對於開發效率的提高還是十分有幫助的。