面向对象第一次总结
前言
這三次作業都是關于多項式求導的問題,不過難度逐步遞進,而且在第三次作業里面加入了嵌套。在前兩次作業中,多項式中的每一項因子確定,所以完成這部分代碼是不太難的,主要是在優化輸出多項式長度上面下功夫;而第三次作業由于存在嵌套,原來的結構不太好擴展,而且讀入、解析上也有很大的改變,所以第三次作業單獨拿出來說。
第一、二次作業
代碼度量
第一次作業事實上只寫了一個類,如下圖所示:
多項式的格式檢查、解析、求導都在一個類中實現,總共代碼200多行,下面是各個方法的復雜度分析:
其中多項式求導復雜度有點高,主要是在優化上的處理有一些分支,其實可以再分一個對項求導的函數出來,可以把函數的結構變得再簡單一點。在第二次作業中,我把多項式的求導函數剝離出來,單獨做了一個多項式計算的類,這樣原來多項式的類只需要關注多項式解析和存儲,計算交給其他類來處理。第二次作業加入了三角函數,代碼在400行左右,依賴關系如下:
?其中Poly是多項式類,用于解析、存儲多項式,ComputePoly用于多項式求導。各方法的復雜度如下所示:
由于多項式中加入了三角函數,以及求導法則的緣故,函數增加了很多,但是基本思路和第一次作業一致。
思路分析
前兩次作業由于多項式每一項的元素固定,每一項的形式比較簡單,只需要幾個指數和一個系數就可以表示,所以采用正則表達式讀入、解析,HashMap存儲多項式,方便合并同類項。
多項式解析
在前兩次作業中,我采用正則表達式來解析輸入,由于一次性判斷整個多項式是否合法存在爆棧的風險,所以我才用單次匹配一項,循環匹配直到不能匹配到新的項為止。
在匹配之前,我先檢查空白字符是否符合要求,然后刪去所有空白字符。這樣在接下來每一項的匹配中就不需要考慮空白字符的位置,簡化正則。除了第一項,每一項前面至少一個正負號,所以我在處理輸入串的時候,判斷了一下第一個非空白字符是否為正負號,如果沒有就添加一個正號,使得每一項都有統一的格式,接下來只需要逐項匹配即可。同時匹配上一項就刪去該項,如果該輸入串符合要求,匹配結束后,字符串應該為空串。
在項的解析中,首先解析每一個因子,比如冪函數、三角函數等,最后再解析有符號整數。先匹配有符號整數有可能導致指數部分先匹配上,發生解析錯誤,然后根據各因子的指數,存到HashMap的相應位置。
多項式求導
在多項式求導中,我是對各個因子進行求導,然后將結果加入到新的HashMap中,最后將HashMap轉成字符串輸出即可。在優化部分,除了對于系數、指數的特殊處理,還有正負項位置的問題,如果正項為首項,那么可以去掉一個正號。
思路總結
總的來說,代碼可以分為三個部分,解析、求導和優化。在解析部分,正則的作用可以說是非常的大,求導和優化就因人而異了,這里使用的HashMap很方便去查找項,包括但不限于合并同類項以及三角函數合并。
bug分析
我在這部分出現的bug主要包括,省略形式的正負號個數、輸入串是否為空等??沾呐袛嗫梢杂肧canner類的hasNextLine來判斷,省略形式的正負號需要對題目有較好的理解。對于大數的處理可以直接用BigInteger類。在第二次優化部分,由于不能在循環中增刪HashMap,所以需要分別構造增刪隊列,在遍歷結束后用于增刪。
第三次作業
代碼度量
第三次作業由于加入了嵌套,java的正則好像不能很好支持,而且項的形式也較為復雜,于是只能像上學期一樣吭哧吭哧寫了個“編譯器前端”,用于解析輸入串,然后使用樹狀結構去存儲整個表達式,最后調用求導即可,具體依賴關系如下:
我在三角函數加入了Factor自變量的位置,用于嵌套,然后對于該三角函數的求導可以套用求導法則得出。整個代碼700行左右,找bug可以說是有點酸爽了。
這里面由于優化等因素,導致復雜度函數的復雜度較大。
思路分析
多項式解析
這部分,經過一晚上的奮斗,我發現我還是要放棄正則,改用編譯器寫法,將表達式分為expression-term-factor三層,其中(expression)也可以為factor,然后逐層解析,邊驗證合法性邊構造樹狀圖。在返回最后一層expression時,應該沒有待解析的字符串了。
在解析之前,首先檢查空白字符的合法性,然后去掉所有的空白字符。在解析的過程中,對可能出現的情況創建if分支,對不滿足所有if的分支,進行錯誤處理,然后遞歸調用。在三角函數內部,由于存在嵌套,所以用factor來作為自變量,先解析嵌套因子,然后創建對應的子類繼續解析。
在解析完成后,進行求導,并將結果存儲下來。因為在term中使用ArrayList存儲,在求導的過程中存在對一項多次求獲取字符串和求導,這樣可以降低一部分的復雜度,同時在debug過程中也可以查看各項的求導結果。
?多項式求導
多項式求導倒是比較形式化,主要是利用求導規則即可,但是如果要優化的話,那么需要創建很多分支去特殊處理。除此之外,對項的求導,往往會有多個項,那么需要對這多個項加括號,保證計算正確,但是對長度的優化稍有不便。
bug分析
在第三次作業中,主要出現的bug主要出現在解析多項式和對多項式求導中。在解析多項式,由于使用“編譯器”的模式,所以需要對各種可能存在的情況進行判斷,稍有考慮不慎,就會有越界的可能性,或者誤報錯誤。在對多項式的求導中,由于三角函數中存在指數,對于各個指數的優化,很容易寫錯求導公式。除此之外,對term進行求導時,有可能會出現多個項相加的情況,那么需要加個括號來保證整體性,不然可能在嵌套結構中出錯,比如對于“sin((sin(x)*sin(x)))”的求導。而且對于term類而言,并不需要繼承factor類,雖然并沒有在代碼中使用,但還算是一個小瑕疵。
具體重構
如果需要重構的話,那么我會針對優化進行重構,重寫equals函數使得各個term表達式可以互相合并。但是對于三角函數合并還是沒有太好的想法,在我的思路中,需要對每個項進行遍歷,尋找可以合并的項,但是目前使用ArrayList存儲,如果強行合并,那么復雜度可能會比較大,可能還是需要使用hashCode函數。
作業感想
這三次作業的難度是逐漸上升的,前兩次作業聯系較為緊密,而且思路也比較直,基本上網上查查資料,寫寫就完了。第三次作業由于嵌套的問題,必須使用新的代碼結構,所以花的時間會比較長。其實如果老師在第一周就和我們說最終的目標的話,那在前兩次作業中,我們就會進行相關的設計,那么第二次和第三次的代碼結構也許用的一樣,會讓我們有更多的時間去考慮優化的問題。
這三次作業下來,基本上熟悉Java的常用容器和一些常規操作,并且對類和繼承有了初步的認識。接下來要對多線程進行學習,免得后面手忙腳亂。
轉載于:https://www.cnblogs.com/Tywin/p/10597203.html
總結
- 上一篇: 『前端规范化』CSS命名规范化
- 下一篇: GenericFactoryMethod