软件工程启程篇章:C#和四则运算生成与运算
0x01 :序言
I leave uncultivated today,
was precisely yestoday perishes tomorrow
which the person of the body implored
?
“看不清楚的時光印痕,像是泛黃的底片,明明還記得那個故事,卻忘了故事里的風月”,不知如今因為生成規則、詞法排序或效率而爭執地面紅耳赤的少年們,多少歲月走過重新翻閱看著七零八落的注釋和代碼段,是否只得慨嘆歲月這把最鋒利的殺豬刀,然而,即便最終能停留在代碼段的注釋行不過寥寥數語,然而乏善可陳卻又萬分鄭重的寫下每一字,想讓她聽起來特別,我聽到她說謝謝我,就像從List<String>.contains()到Hashtable.Add(string.getHashCode(),string)的變化,就像從Number.Created()到CreatedList.Created()的變化,正確性,結構化,效率。
謹以此文致以軟件工程的啟程,你好,舊時光
?
0x02 :軟件工程和PSP表格記錄
I am a slow walker,
but I never walk backwards.
Although with hippopotomonstrosesquippedaliophobia and bugphobia
?
| PSP 2.1 | Persinal Software Process Stages | Time(Estimated) | Time(Real) |
| Planning | 計劃 | ? | ? |
| Estimate | 估計這個任務需要多少時間 | 8h | 17h |
| Development | 開發 | ? | ? |
| Analysis | 需求分析(包括學習新技術) | 1~2h | 2~3h |
| Design Spec | 生成設計文檔 | 20~40min | 20min |
| Design Review | 設計復審 | 5~10min | 1min |
| Coding Standard | 代碼規范 | 20~40min | 20min+2h(*) |
| Design | 具體設計 | 1~2h | 15min+2h(*) |
| Coding | 具體編碼 | 2~3h | 6~7h |
| Code Review | 代碼復審 | 30min~1h | 30min+2h(*) |
| Test | 測試 | 1~2h | 1h30min |
| Reporting | 報告 | ? | ? |
| Test Report | 測試報告 | 30min~1h | 20min |
| Size Measurement | 計算工作量 | 1h | 2~3h |
| Postmorten & ProcessImprovement Plan | 事后總結, 并提出過程改進計劃 | 30min~1h | 1h |
| ? | 合計 | 8h15min~ 14h30min | 16h16min~ 19h16min |
表格補充說明:(*)表示因為前期思考時間不足而重構所增加的時間
?
對于C#和四則運算生成和計算,首先我們確定基本的功能模塊(http://www.cnblogs.com/jiel/p/4810756.html)
??????? 對于參數range和number,能夠依據參數生成特定的四則運算表達式,對于必須的基本要求,我們必須確保生成子表達式結果非負數,同時運算符個數也不超過3個,而且各表達式不能通過有限次的乘法或加法交換為同一道試題
??????? 對于參數range和number,在實現基本功能的前提下需要考慮的是性能和效率的問題,比如:“生成的表達式中是否各符號的出現率相差不超過10%”,“括號的出現是否具備較強的隨機性”,“表達式的數值是否均勻分布在[0,range]區間”,“查重或者所定義的規則是否具備較高的時間效率”
??????? 對于參數exercise和answer,我們需要能夠解析標準的四則運算表達式并將它計算出正確結果,與answer文件進行對照從而記錄正確與錯誤題號
??????? 對于參數exercise和answer,在解析并計算標準的四則運算表達式時應盡可能快速地計算出正確結果,而對于逆波蘭表達式,其時間復雜度為O(kn),而其他效率更高的算法也只是對常數k進行優化,且實現的復雜度極高,因此不妨直接選取逆波蘭表達式作為解析方法
?
0x03 :項目設計文檔基本思路
1 universe, 9 planets,
204 countries,809 islands, 7 seas,
and i had the privilege to meet you.
?
??????? ? 由基本的功能模塊,我們可以將此次個人項目分解為階段性的模塊工作:
?
??????? 在底層上,需要實現同時支持{數域:真分數,自然數}{運算符:四則運算符,左右括號}的數據結構或類
??????? 在功能層次上,主要實現表達式的構造、生成和計算,并能通過中綴表達式向后綴表達式的運算實現計算結果的正確性
??????? 同時,我們能盡可能在盡可能的大的范圍內實現表達式的構造,同時又必須保證不具備重復性,且減法和除法有效性不能被破壞
??????? 在前端層次上,主要實現命令行參數的解析,最終實現函數所具備的的生成和計算功能
?
0x04 :UML圖的設計思路整理與程序正確性證明
To the world,you maybe a person.
But to a person,you maybe the world.
?
?
?
?
0x0401 Number基礎類的架構
?
internal class Number
{
??????? /*Basic Parameter for class Number (Random with the parameter of -r)*/
??????? private long parent;
??????? private long child;
}
由UML圖的基本架構中,在Number類的基礎類的構造中,不僅需要設置存儲形式為“假分數”即(child/parent),同時重載了基礎的四則運算(但未同C++時重載運算符),同時重載(Override)ToString()方法,保證在輸出的時候仍為標準形態的真分數;
?
因此,基于此數據結構的架構,我們隱性地做出了如下的定義:
?
??????? 假分數實現基本的加減乘除運算,同時為盡可能擴大假分數的運算范圍,我們在每調用計算的時候都會調用最小公約數gcd()函數(由于為O(log)級的算法,所以可以相對忽略此時間消耗),從而保證計算效率
??????? 若恰為整數,則強制要求分母為1即可
??????? 在打印的過程中,將通過重載ToString()函數保證輸出的正確性
?
因此,對于程序的正確性,通過覆蓋性的單元測試(共4 * 4 * 4 = 64種),即將Number劃分為int類型的自然數,long類型的自然數,真分數,帶真分數四種情況對程序進行測試,運算結果符合預期,因此通過單元測試不妨默認程序在此測試樣例的情況下程序正確運行,因此,在無特例的情況下不妨認為Number類滿足程序正確性
?
0x0402 ParseNumber基礎類的架構
?
internal class ParseNumber
??? {
??????? private String parse;
??????? private Number result;
??????? private Regex regex_1 = new Regex("^[1-9]{1}[0-9]*['][0-9]+[/][1-9]{1}[0-9]*$");
??????? private Regex regex_2 = new Regex("^[0-9]+[/][1-9]{1}[0-9]*$");
??????? private Regex regex_3 = new Regex("^[0-9]+$");
}
?
ParseNumber類通過正則表達式的檢測實現字符串類型變量expression到Number類型的轉換,而若無法通過正則匹配時由于字符串切分工作通過其他類正確實現,因此,可直接構造拋出new NotImplementedException();,通過屏蔽機制在Main函數中try-catch捕獲即可,對于功能模塊的此類,只能通過單元測試來盡可能保證程序正確性,因此與Number類的程序正確性證明類似,不妨在無特例的情況下認為ParseNumber類滿足程序正確性
?
0x0403 Poiland/MyApp類的架構
?
Poiland類通過通過數據結構棧的使用實現后綴表達式的快速解析,在注釋中有著較好的說明:
/* Kernel Method
?* - Poiland temp = new Poiland(String);
?*?? temp.getResult();
?*??
?* = String presents for the input of expression(Type:String)
?*?? Init Object temp with initation of input and convert to Behind-Expression
?*?? Cal Such Expression with Stack
?*/
而MyApp類提供Main函數入口,因此這兩類程序正確性證明暫時可認為滿足程序正確性,主要將針對CreatedList類展開程序正確性的論證
?
0x0404 CreatedList類的架構
?
CreatedList類主要實現隨機四則運算表達式的生成,我們首先確定這樣的基礎思想,在任何range參數的取值情況下,生成數量與重復率成正相關,但在range參數足夠大時,若通過隨機化方法生成操作數和操作符隨機組合,重復概率極小,理論計算基本處于1%%的數量級,甚至在隨機化的處理方法上,表達式重復概率基本可以忽略不計,而若通過查重的方式逐步插入將占用大量的時間消耗,其消耗的CPU的資源率相當高,甚至在此前測試時占據96%的采樣資源;
因此,這里我們從兩方面入手分析這一問題,如何構造不重復的表達式,如何快速查詢表達式的重復性
?
??????? 如何構造不重復的表達式
這里,我們采取子集生成的方式,對于隨機的表達式集合,我們只生成其中的一部分子集,這里對子集做出如下的定義和證明:
? 表達式的操作符數和數字數具備“數字數 - 操作符數(不含括號) = 1”的數學關系,因此可將操作符隨機選取依次穿插在數字間,生成中綴表達式
? 表達式的數字必須呈遞減關系,且與非遞增關系不同,我們必須確保生成的表達式的相鄰三個數字不相同,從而保證表達式可以直接通過String.Equals()方法進行判斷
? 對于減法關系的生成,我們必須不妨定義相鄰符號組為“[—][+][+|—|×|÷]”或“[+][ —][+]”或“[—][+]”或“[+][ —]”或“[ —]”的組合
?
這里證明,對于交換性質的運算符+和×,對于A≥B,則A[+|×]B = B[+|×]A,當且僅當A=B,在此基本定理的情況下,可以證明直接通過String.Equals()方法實現表達式的查重
?
這里放置兩張優化圖,說明List<String>.Contains()和Hashtable.Contains()的優化程度(getHashCode()方法),這里我們設置參數為“-r 1000 –n 100000”
?
?
?
未優化前對List<String>.Contains()函數的觀察可以據此判斷
?
?
?
優化后Hashtable.Contains()函數的觀察可以據此判斷
?
因此,實際上,Hashtable的優化,基本可以使得查重的效率呈現數量級上的差異,同時由于任何運算過程中,包括Number的識別和轉換都需要調用正則表達式進行判斷,因此對于100,000道題目的生成,是相對可以容忍而若需要優化,可能會涉及到代碼重構的操作
?
0x05 :測試樣例與代碼分析
To the world,you maybe a person.
But to a person,you maybe the world.
?
這里測試樣例僅針對“-r -n”的類型操作進行說明(特別說明,若非從命令行中讀入,而是通過VS的調試窗口進行讀入,應屏蔽MyApp.exe的參數,只敲入-r integer –n interger進行測試,通過cmd則不會講MyApp.exe讀為args[0])
?
CreateMaths.exe –r 1.3 –n 5.6
Print the IndexOutOfRangeException's Message As Followed :
[Message Start]
索引超出了數組界限。
[Message End]
Less Args is Invalid, Such Args Are Valid:
? Myapp.exe -r 10 -n 10
? Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt
Press Enter to Exit
?
CreateMaths.exe –r 10000 –n 100
Print the StackOverflowException's Message As Followed :
[Message Start]
沒有足夠的內存繼續執行程序。
[Message End]
Range parameter(-r) is too large
Press Enter to Exit
?
CreateMaths.exe –r 10000 –n 100
Print the StackOverflowException's Message As Followed :
[Message Start]
沒有足夠的內存繼續執行程序。
[Message End]
Range parameter(-r) is too large
Press Enter to Exit
?
CreateMaths.exe –r 5000 –n 100
argument's carried out successfully of -n -r
Press Enter to Exit
?
CreateMaths.exe –r 3 –n 10000
class CreatedList : NotSupportedException Happening!
Print the NotSupportedException's Message As Followed :
[Message Start]
不支持所指定的方法。
[Message End]
You May Well Input "-r 1 -n 10", Large but not Larger -r or -n is welcome
Invalid args Mainly Because number is out of the limition of range
Press Enter to Exit
?
CreateMaths.exe –r 100 –n 100000
argument's carried out successfully of -n -r
Press Enter to Exit
?
測試答案的測試用例由于文件較大,在此不再展示,圍繞文件讀取合法性、題目格式的正確性、答案格式的正確性、題目文件和答案文件是否匹配、答案正確的題目數量等方面設計測試用例即可
?
0x05 :測試樣例與代碼分析
To the world,you maybe a person.
But to a person,you maybe the world.
?
在代碼分析上,我們不妨采取設置參數為生成10000道范圍限制在100內的四則運算表達式
?
?
?
?
顯然, Hashtable的優化,基本可以使得查重的效率呈現數量級上的差異,同時由于任何運算過程中,包括Number的識別和轉換都需要調用正則表達式進行判斷,因此對于10,000道題目的生成,是相對可以容忍而若需要優化,可能會涉及到代碼重構的操作,因此其改進空間應只涉及重構層次上的修改,在此次優化過程中,可以判定為改進空間不大
?
0x06 :個人項目總結
To the world,you maybe a person.
But to a person,you maybe the world.
?
個人項目,實現和設計的差異性可能只有深入思考才會去探究清晰,工程項目不同于理論學習最大的特征在于測試的完全性和程序本身的魯棒性,可能時候面向對象建模課程的影響,在處理輸入的參數時總會考慮大量內容,從而確保項目能夠在任何輸入的情況下均能完美給出相對的錯誤信息和輸出信息;
同時,自己在初期設計的時候沒有梳理清楚“表達式的生成規則”和“基礎的類的設計”,導致類之間的關聯與預期偏離,不同功能交叉在不同對象之間,極大增加了思維難度,從而導致后續的重構消耗了大量的時間,可能軟件工程最大的目的,在于,用清晰的設計實現優美的代碼,以上
?
Hola~BugPhobia With Pocket Panacea
轉載于:https://www.cnblogs.com/panacea/p/4831018.html
總結
以上是生活随笔為你收集整理的软件工程启程篇章:C#和四则运算生成与运算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UILabel自适应高、宽
- 下一篇: 201509280825_《css3——