BUAA_2020_OO_第一單元總結

三次做業,三次成長正則表達式

第一次做業——冪函數求導總結

做業思路和心得

第一次做業的要求只有x的指數這樣的冪函數加減組成表達式,對錶達式進行求導,並且沒有格式錯誤的檢查,因此難度感受還不是很高。不過因爲我寒假的preview做業還有兩個task沒有作完,因此我感受本身對語法和字符串處理等方面還不是很熟練。所以,雖然看起來第一次做業難度不高,可是我仍然十分認真地對待它,把它看成鞏固本身基礎的一次機會(以後的做業就沒機會鞏固基礎了
進入正題,第一次做業因爲只有一種冪函數,因此個人思路也比較簡單:直接用TreeMap存儲x的係數和指數,其中以指數做爲Key以便於合併同類項。求導規則也很簡單,只需將TreeMap裏的每一個元素取出來係數乘以指數輸出爲係數,指數-1做爲新指數就完成了求導過程。
第一次做業讓我調試了好久的地方是用正則表達式讀入輸入並進行分割,因爲我對正則表達式掌握不熟練,期間查閱了衆多資料和助教發的教程,最終在不斷的摸索和嘗試下,我寫出了那個分割輸入的正則表達式,寫出正則後,後面的處理就顯得簡單不少了。第一次做業讓我對正則的瞭解更深刻一步。編程

程序結構分析

  • UML分析
    第一次做業因爲對面向對象思想理解不夠,同時做業結構較簡單,因此我在第一次做業只有一個Main類,有131行,類圖也只有一個類,就不上圖了。(之後要是再這麼寫就要次次重構了呢!數據結構

  • 複雜度分析

    從分析表中能夠看出,個人第一次做業中的getInf方法的設計複雜度和圈複雜度都較高,迴歸代碼本人確實發現這個方法中if-else的結構嵌套較多且邏輯較複雜,同時因爲它是第一次做業提取因子的主要方法,因此其被其餘方法調用的次數也較多,致使其和其餘方法的耦合度也較高,設計複雜度太高,致使其擴展性和複用性較差。架構

hack與被hack

第一次做業給了我慘痛的教訓。我在強測中只得了18分,爲何呢?緣由就在於我在優化過程當中對正數的輸出我誤覺得只會在開頭,因而把+省略了(大概腦子一抽,捂臉.jpg),致使了我在強測中大量的輸出格式錯誤,也就致使了我沒有機會進入互測,第一次做業中也就沒有獲得什麼hack別人的經驗。函數

第二次做業——冪函數加三角函數求導

做業思路和心得

第二次做業除了冪函數還外加了三角函數,不過好在三角函數內部只能是x,這樣全部輸入的形式也最終能夠化爲三種:xa,sin(x)b,cos(x)^c。那麼這樣的話,我依舊能夠沿用第一次做業的整體思路,即用TreeMap進行輸入因子的存儲,只不過此次的Key要新建一個類來存儲三個因子各自的指數,求導方法的話也只需分紅六類便可(三種因子隨意組合——6種)。此次惟一與上一次不一樣的是多了WF判斷。那個人思路是,既然錯誤那麼多,找也找不全,不如構造正確的表達式的正則表達式,輸入的能匹配,那就OK,匹配不上那就確定是WF。這種思路避免了WF的漏判。
但因爲此次輸入複雜了一些,同時還要構造正確的正則表達式來判斷格式,讓我在第一次做業中學習到的正則表達式知識又捉襟見肘了。因而我在第二次做業期間,又花了一部分時間去學習更高級的正則表達式用法,最終第二次做業也是用正則表達式的形式來讀取輸入,判斷格式,效果還不錯。作完第二次做業,我感受本身對正則表達式又有了更深一層的理解。第一次做業結束感受本身正則表達式掌握的不錯了,第二次做業結束讓我感受本身對正則表達式還有不少須要學習的地方,由於越是深刻越是發現正則表達式的高級用法還有不少我所不知道的。我要在從此的學習中進一步深刻了解正則表達式的用法和原理。性能

程序結構分析

  • UML分析

    第二次做業中我是在第一次做業的基礎上添加了三個類用來存儲三個因子做爲一個總體信息單位的信息。看起來有了一點OO的意味,可是寫完三次做業回頭來看,本人第二次做業使用的類並非爲了構建OO的思想架構而是在無可奈何的狀況下爲了沿襲第一次做業的TreeMap思想,不得已加入幾個存儲信息的類。那些類的做用實質上僅僅封裝了數據,相似於C語言的結構體,實際上並無什麼架構上的改變,這是我須要在從此的設計中進行改進的。類的做用不該僅僅侷限於封裝數據,而是發揮它們真正強大的功能。學習

  • 複雜度分析


    第二次做業的總體結構較第一次做業明顯複雜了許多,因此總體複雜度也有所上升。圖中所示個人main方法基本複雜度是最高的,其餘複雜度也很高,緣由在於我給TreeMap的排序接口comparator進行了重寫,由於Key是我本身定義的類。這部分重寫我須要對自定義類裏的三個指數依次進行比較判斷,致使if-else結構不少,複雜度提高。以後查資料我發現這個方法重寫也能夠在自定義類內進行,這樣能夠大大下降main方法的複雜度,讓main方法看起來更簡潔。
    除了main方法,還有幾個方法複雜度較高。Stringprocess、display、judgekind等方法複雜度都較高,這就是我在UML分析裏所說的,我在第二次做業中新建的幾個類並無幫助我下降總體結構的複雜度也沒有下降耦合度,僅僅是封裝了數據,因此複雜度高的方法內部仍然有許多if-else判斷和過程式的殘留痕跡。這些都須要我在之後的學習中盡力克服,養成良好的習慣和思想。測試

hack與被hack

我在第二次做業中終於第一次體會了互測的快(刺)樂(激)。我第一次有機會看到別人的代碼,我抱着學習的心態,把每一份代碼都下載下來看一看。可是我發現除了幾份架構清晰、邏輯至少能看明白的代碼外,其餘的真的很難理解,也不知道他想幹什麼。因此,我決定不用徹底看懂代碼,直接上測試數據。
測試方面,我其實不習慣於使用本身搭建的評測機,由於我以爲那樣覆蓋性很差,並且重複數據較多,效率不高。我更喜歡本身根據指導書,本身手動構造一些特殊易錯數據進行本身的測試和互測的用例。實踐證實,互測中我使用的都是我本身在寫代碼的時候本身積累下來測試本身程序的用例,效果還能夠,至少每組數據都至少能hack到一個房間內成員。
第二次做業我本身程序的bug又是出在了化簡的過程,又是在某一種狀況下少輸出了一個+(再一再二,不能……優化

小提示(給本身之後準備的

JAVA語言中類是引用類型的,因此當類做爲參數傳遞時,對參數的操做也會對外部的類變量產生改變。因此在相對類的部分進行操做併產生新的類時,必定要進行clone或是copy。在本次做業中我就使用了這種方法來進行操做,先來看代碼:網站

```

public static Inf CopyInf(Inf a) {

    Inf newInf = new Inf(null, null);

    if (a.getKey().getXindex() != null) {

        newInf.setKeyX(new BigInteger(a.getKey().getXindex().toString()));

    }

    if (a.getKey().getSinindex() != null) {

        newInf.setKeySin(new BigInteger(a.getKey().getSinindex().toString()));

    }

    if (a.getKey().getCosindex() != null) {

        newInf.setKeyCos(new BigInteger(a.getKey().getCosindex().toString()));

    }

    if (a.getCof() != null) {

        newInf.setCof(a.getCof());

    }

    return newInf;

}```

這段代碼是我在進行乘法求導時,對其中一個因子進行求導,剩餘的不變時,要進行這個方法的調用,進行信息的複製。可是以後我查資料發現,JAVA中的基本類型(int,String等)和基本類型包裝類(Integer,BigInteger等)這兩類變量是不會致使內部信息變化的,因此其實在我這個第二次做業中,不進行信息複製也是能夠的。不過我在這裏就是想給之後的本身和看到這篇文章的讀者們提個醒,在對同一個類進行屢次操做且每次操做都要基於原始數據的狀況下,不要忘記進行clone或是copy。否則這種隱蔽的錯誤真就寫bug一分鐘,debug到兩點鐘。

第三次做業——嵌套表達式求導

做業思路和心得

第三次做業較以前兩次難度再次提高。我感受難度最大的部分就是輸入的讀取和WF的判斷。因爲增長了嵌套表達式,整個輸入的結構變得十分靈活而複雜。表達式裏會有因子,因子裏又會有表達式,這樣對輸入的處理是極大的困難。
爲了提升性能,我採用了WF判斷和輸入的分析讀取合在一塊兒進行。先使用第二次做業中的Stringprocess方法將多餘的符號去掉,再從頭開始循環讀取。讀取的時候,判斷括號數量是否匹配。其他WF在讀取以前先遍歷一遍字符串進行判斷。
讀取好各個因子後,就能夠創建表達式樹,建好後就按鏈式求導法則,對整棵樹進行求導,求導後輸出便可。在此,我要提一下個人初版方法,就是將求導方法交給每一個類內部本身管理,每一個類內部也有本身的數據,這樣,我最開始的想法是讓類本身調用各自的方法,遞歸求導。可是我實現後發現,這樣複雜度和空白數據量都太大了,並且邏輯也不清晰,就放棄了這個方法。最後選擇了建樹的方法。因爲本身的數據結構基礎也不夠紮實,在學習創建表達式樹的期間也費了好一番力氣,查閱了大量網站資料。因此,我要告訴本身,基礎要打好呀!(相信如今說爲時也還不晚

程序結構分析

  • UML分析

    因爲此次結構較複雜,因此爲了減小代碼量,我使用factor做爲四種因子的父類,減小重複代碼。此外,因爲個人StringProcess和WF都是從新遍歷了輸入,因此與其餘模塊關聯不大,我以爲這讓個人這兩個模塊提升了可移植性和重用性,因此這兩個模塊是我較爲滿意的模塊。表達式樹的那幾個模塊,因爲以前我對樹的掌握不牢,致使這部分建樹沒有什麼思路上的創新,按照固有方法和套路進行編寫。也致使了以後輸出的化簡很難操做。

  • 複雜度分析



    因爲程序複雜度的提高,方法的數量也大幅度提高,方法的複雜度卻是沒什麼巨大的增長。我分析緣由在於我進行重構,選擇表達式樹以後,以前的一些複雜的大方法被我拆解爲各個小方法放到類中,本身管理。因此方法的數量增長了,可是複雜度沒什麼暴增。

hack與被hack

第三次做業我本身的程序的bug主要出在WF判斷這部分,我在本地本身測試時,就發現不少不應判WF的判成了WF,該判WF的卻輸出告終果。我對這些問題對程序打了不少個補丁,可是在強測和互測中仍是發現了幾個本身沒有發現的點,致使了錯誤。這讓我明白了本身構造數據的時候的方法有問題,我會在從此的做業的構造數據的過程當中,注意改正,爭取獲得更好的測試效果。
在第三次互測中,隨着程序體積的膨脹,徹底閱讀懂代碼變得更加不現實了,因此我依舊採用第二次做業的方法。在互測中提交本身本地測試出現問題的用例,同時想想別的經常使用方法會出現什麼問題。效果也仍是不錯,不多有無效用例,大多都是找到了同組人員的bug的。

總體感悟思考

從寒假的一無所知到preview的有所瞭解到unit1的稍有理解,能夠說這門課程讓我一步步地走進了面向對象編程的世界。這一級級臺階也要感謝課程組的老師和助教們。 可是回頭看來本身的三次做業,發現面向對象的一些經常使用的pattern尚未靈活運用,一些經常使用的思想也尚未深刻理解。這些都須要我在從此的課程中努力學習,盡力理解的東西。 我也在第一單元做業的歷練中,發現了一個適合本身的寫測結合的方式。我喜歡每寫完一部分就認認真真、仔仔細細地測試一遍這一部分的功能是否正確。直到在我看來,這部分寫完的代碼功能上徹底沒有問題我纔會繼續寫下去。這樣我感受雖然用時較多,可是寫起來讓我本身感受更加安心,同時也讓debug的難度有所減少。我感受是適合我本身的編寫方法。我會在從此的做業中,繼續使用這種方法,但願可以取得良好的效果。

相關文章
相關標籤/搜索