OO第一單元做業小結

前言

  第一單元的主題是表達式求導,第一次做業是隻帶有常數和冪函數的求導,第二次做業加入了正餘弦函數,第三次做業又加入了表達式嵌套,難度逐漸提高。整體來講前兩次做業還易於應對,而第三次做業作得相對有些艱難。並且這其中還有不少巧合,第二次做業延時到了週三上午,而我在週二晚睡覺前通過本地測試又找到一處致命BUG,一直改到一點才交上;第三次做業一開始中測的最後一個點一直沒有經過,週二找了一天原本已經放棄,後來得知做業又延時到週三中午,成功在週三上午找到了那處BUG,並正好用完十次無償提交次數,終於過了所有中弱測。若不是這兩次延時,第一單元的做業恐怕已經崩掉了。正則表達式

1、三次做業的代碼分析

一、第一次做業

(1)類圖與複雜度:數組

            

(2)程序分析函數

  僅用了兩個類。主類Derivation僅包括主函數入口。類Exp中包含一個private屬性str[],它是用來儲存項的字符串數組;四個方法,其中Exp()是構造方法,同時進行格式合法性判斷和拆項,getLength()用來得到str的元素個數,diff()用於處理每一項、求導並將結果中的同類項合併,pri()用於輸出求導結果。性能

  能夠看出diff()的方法規模較大,由於這個方法同時具備按狀況處理項、求導、合併同類項三個功能,能夠將這三個功能拆成兩個或三個方法來寫。Derivation類約有35行代碼,Exp類約有115行代碼,總共約150行代碼。學習

(3)優缺點分析測試

  第一次做業個人代碼整體仍是比較面向過程,基本上按照C語言的模式去寫的,面向對象的思想不夠深入。spa

二、第二次做業

(1)類圖與複雜度debug

 

(2)程序分析設計

  第二次做業的總體思路是處理表達式後,分別得到每一項的係數、x的指數、sin(x)的指數、cos(x)的指數四個ArrayList,求導時則是係數乘以某一個因子求導的結果再乘以其餘因子。對象

  總共有Derivation二、Exp、Diffx、Diffcos、Diffsin五個類,其中Derivation2包含主函數的入口,Exp用於判斷表達式合法性、處理表達式並進行求導結果的輸出,Diffsin、Diffcos、Diffx分別是對三類函數的求導處理。

  能夠看出,Diffx、Diffsin、Diffcos三個類中的pri函數(對求導結果的輸出函數)代碼複雜度較大,由於其中爲了簡化輸出結果,用了不少if-else語句判斷指數爲0、一、2等以及指數爲負等狀況。還有Exp類中的getList()方法(用於得到各個因子的指數)也用了不少if-else語句判斷三種因子是否省略指數等狀況。

  另外,Exp中的private屬性過多,由於判斷表達式合法性的方法超過了60行,我就將三種因子及常數因子的正則表達式寫到了類的private屬性裏。

(3)優缺點分析

  寫第二次做業時其實並無徹底理清思路,不少方法構造的比較複雜,甚至有爲了縮減方法行數將方法內的變量移到類的屬性中的草率決定。

三、第三次做業

(1)類圖與複雜度

      

 

(2)程序分析

  第三次做業的總體思路是先將輸入的表達式進行遞歸判斷是否合法,而後進行鏈式求導,其中存在對各類因子求導、對項求導與對錶達式求導的相互調用。

  共九個類,Main包含主函數入口,Exp用於遞歸判斷表達式合法性,Factor做爲父類,Da、Dx、Dsin、Dcos、Dterm、Dexp都是Factor的子類,分別用於對常數、冪函數、正弦函數、餘弦函數、項、表達式求導。

  能夠看出方法複雜度最高的是每一個子類中的diff()方法(求導函數)以及Exp中的exchange()方法(遞歸去括號)和judge()方法(判斷合法性),由於其中都用了不少if-else語句判斷各類狀況。

(3)優缺點分析

  我的認爲第三次做業仍是存在一些優勢的,好比我獨立完成了遞歸判斷合法性代碼的編寫。缺點是沒有對結果進行化簡,個人程序是變求導邊直接打印結果的,其中只有一些簡單的指數爲0、一、2等狀況的簡化,其它的都是直接輸出,還存在不少無心義的括號。

2、三次做業的BUG分析

一、第一次做業

  第一次做業強測中有一處BUG,互測沒有被找出BUG。

  第一次做業原本也比較簡單,我也作告終果的簡化,包括首項爲負時正項提早的化簡也作了,本覺得應該一百分,結果強測有兩個點沒過。

  這兩個點都源於同一處BUG,我在求導以後合併同類項時,忽略了合併後係數爲零的狀況,也就是說我將係數爲零的項也輸出了,但本應該只是扣性能分,結果應該是正確的,但我在鏈接每一項時只判斷了係數大於0時添上+號,由於係數爲負時輸出的BigInteger會自帶符號,因此我對於係數爲0項的輸出前沒有加減號,也就產生了相似於x^20*x的不合法結果。這個BUG本質上仍是粗心了,只考慮了輸入時將係數爲0的項忽略,而沒將合併後係數爲0的項排除。

二、第二次做業

  第二次做業強測中有一處BUG,互測沒有被找出BUG。

  個人求導思路是對每一項的每個因子分別求導,並將某個因子求導結果乘以其它因子,而我判斷了若是某個因子求導結果的指數爲0,將其忽略,但我在輸出時卻無條件地在求導因子外的其餘因子前輸出一個*號,也就產生了相似於+*x的不合法結果。

  還有一點值得一提的是我在週二極限de到凌晨一點的BUG,那就是我在對輸入的表達式進行同類項合併時,因爲我用了四個ArrayList分別儲存每一項的係數、冪函數指數、正弦函數指數與餘弦函數指數,我在判斷同類項時寫成了只要在三個存指數的ArrayList中找到了與當前項各個指數相同的元素,就將係數相加而不添加新的指數元素。但這樣假如輸入一個x+sin(x)+cos(x)+x*sin(x)*cos(x)的表達式時,就會將第四項判斷爲以前出現過同類項,而將表達式化簡成2*x+sin(x)+cos(x)。因此在判斷同類項時,應該判斷在ArrayList中是否有當前項的各個指數全都對應存在的元素,若是有才是真正的同類項。

三、第三次做業

  第三次做業強測與互測中都沒有被找出BUG。

  這裏分享我當時中測最後一個點死活de不出來的BUG。我在遞歸進行合法性判斷時,先判斷括號中的內容是否合法,若合法將括號及其中的內容直接替換爲字母x或字母e(換爲e即表明當前括號及其中的內容是一個表達式因子)。我在替換時用到了replace函數,可是replace會一次性替換全部相同子串,例如輸入的表達式是(x)+sin(x),我就會在第一次替換時直接將原式替換爲e+sine,即認爲正弦函數括號中爲一個裸的表達式,從而判斷爲WF。因此應該用replaceFirst函數僅替換剛找到的子串。這裏還須要注意的一點是,replace函數替換的是子串,而replaceFirst函數替換的是第一處符合正則的子串,也就是說,在找到一個括號子串(設爲字符串s),在用replaceFirst函數式應先將s中的+、(、)等字符前加上轉移符,以將s轉換成正則表達式再使用replaceFirst函數。

3、互測時找BUG的策略(love and peace)

  因爲本人很菜,前兩次互測時都是先手動輸入一些易錯數據以及本身寫代碼時曾經出現BUG的數據來判斷輸出的正確性,而後就是肉眼debug了,即閱讀被測代碼的設計結構構造相應數據。這樣的策略雖然效率不是很高,不過也能找到明顯的BUG。在第三次互測時作了一次伸手黨,從隔壁大佬那裏整來了一個對拍器,找BUG的效率的確高不少。

4、Applying Creational Pattern

  每次做業中都有不少方法有不少if-else語句,其實有的能夠拆分紅多個方法去寫。

  第三次做業寫的時候對繼承的用法還不夠熟悉,程序的實現對繼承的依賴並不大,也並無使用接口,存在重構的必要。

  另外但願能夠經過學習本身寫出對拍器。

相關文章
相關標籤/搜索