結對編程項目報告--四則運算CORE

<!doctype html>css

sw_lab2.md

結對編程項目報告--四則運算CORE

第15組:JL17110067 隆晉威 PB16120853 趙瑞html


項目GitHub地址

https://github.com/NiceKingWei/homework2node

PSP

status stages 預估耗時 實際耗時
Accepted make plan 20 min 20 min
Accepted demand analysis 40 min 40 min
Accepted analysis 45 min 90 min
Accepted code 3 hours 5 hours
Accepted test 2 hours 3 hours
Accepted report 1 hours 2 hours
Sum   8 hours 12 hours

項目需求

像《構建之法》的人物阿超那樣,寫一個能自動生成小學四則運算題目並給出答案的命令行 「軟件」, 若是咱們要把這個功能放到不一樣的環境中去(例如,命令行,Windows 圖形界面程序,網頁程序,手機App),就會碰到困難,由於目前代碼的廣泛問題是代碼都散落在main ( )函數或者其餘子函數中,咱們很難把這些功能完整地剝離出來,做爲一個獨立的模塊知足不一樣的需求。python

API

  1. setting() function:ios

     
        
        
        
        

    就是能夠屢次改變設置,在傳入參數的時候,max_opearatorsmax_rangeprecision能夠傳入值或者-1,傳值表明更改該設置,-1表明不變。has_fractionhas_real能夠傳入1,0,-1;1表明開啓,0表明沒有,-1表明不變。c++

  2. generate函數:git

     
        
        
        
        

    將參數傳進去,運行後結果就存在了string* answer裏面。github

 

代碼邏輯思路

咱們首先定義了 fraction 類,這是分數類,用於符號計算。web

 
  
  
  
  

fraction 類裏面重載了各個運算函數,並在每次計算結束以後經過類中的reduction()函數把分數變爲最簡分數。編程

而後定義了一些工具函數,如輸出函數,判斷是不是無效值的函數 is_bad_value

 
  
  
  
  

is_bad_value 是一個判斷值是不是壞值的函數。壞值在除零異常時可能會出現,在值超出範圍的時候也會出現。壞值具備傳遞性,壞值和任何值運算的結果都是壞值。這種設計方式的靈感來自函數式語言中的 Maybe Monad ,下面放一下fraction operator / (const fraction x) const;做爲例子:

 
  
  
  
  

 

接下來定義抽象語法樹的結構。

 
  
  
  
  

每個抽象語法樹的節點都包含兩個字段,一個是 type,一個是 data。type 的類型是一個枚舉值,data 是一個 union 聯合體。這種作法的靈感也來自函數式語言。在表示抽象語法樹時,tagged union 是一種很好的方式。但由於不肯定能不能使用 c++17,因此咱們並無用類型安全的 std::variant ,而是使用了本身定義的tagged union

以後的事情就比較簡單了

 
  
  
  
  

這兩個函數產生隨機值和隨機抽象語法樹,根據 setting 的規則產生合適的表達式樹。

這兩個函數的代碼:

 
  
  
  
  

 

 
  
  
  
  

calc_asttree 是遞歸函數,它遞歸調用自身,計算左子樹和右子樹的值,而後再計算當前節點的值,若是有一個結點的type是TYPE_DOUBLE,那麼返回給上一層的type就是TYPE_DOUBLE

這兩個函數的代碼

 
  
  
  
  

ast_eval 是調用 calc_asttree 的函數,它先把 hash_code 設爲0,而後調用 calc_asttree

calc_asttree 遞歸計算的過程當中會產生一個操做序列,這個序列能夠刻畫當前表達式的特徵,例如 1+2+3,在計算過程當中產生的序列是 1+2=3, 3+3 =6,3+(2+1) 在計算過程當中產生的序列爲 2+1=3,3+3=6。若定義兩個序列等價當前僅當序列中每一個算式在交換律意義下等價。能夠發現,題目要求的 「重複」 條件與計算序列的等價條件是等價的。所以,咱們能夠用計算序列來去重。

但計算序列的儲存比較佔空間,所以咱們選擇了一個哈希函數,對計算序列進行哈希映射。由於兩個序列哈希值相同是兩個序列重複的必要條件。所以在實際操做中,只須要兩個序列哈希函數不一樣,則這兩個表達式必然不相等。

接下來是表達式輸出函數。

 
  
  
  
  

註釋中的內容是咱們的計算表達式的 BNF 範式。由語法產生式,咱們能夠很容易地寫出以上遞歸函數,並經過函數間的互相調用完成對錶達式的輸出,這種輸出方式不會產生多餘的括號。

 
  
  
  
  

generate 函數生成題目和答案。它先調用 random_ast 生成一顆隨機語法樹,而後對它進行求值,若是結果是壞值,那就從新生成一個。

特別值得一提的是咱們的 main 函數

 
  
  
  
  

它爲每一組數據生成了一行 python 代碼,是一句斷言。只要斷言成立,這組數據就是正確的。只須要簡單改改更改參數,咱們就能夠得到不少組數據,並能經過腳本進行自動測試。

 
  
  
  
  

發佈前,咱們組一共測試了 500萬 組數據,均沒有出錯。

BUG記錄

出現了錯誤的計算結果:

  1. bug緣由:咱們倆搞錯了乘方和乘法的運算優先級,
  2. 這個不太容易避免,出錯了時候咱們還疑問到底該先算乘方仍是從左到右乘
  3. 大概四十分鐘,找到錯誤樣例,研究錯誤樣例就能夠了,發現了是邏輯錯誤,那麼改代碼就能夠了。

第二次出現了錯誤的結果:

  1. bug緣由:分數運算的中間結果分子溢出了long long的範圍
  2. 這個bug是在寫函數時候錯誤的估計了可能用到的範圍,沒有增強函數的魯棒性。
  3. 調試方法:用錯誤樣例逐步測試,觀察中間結果。
  4. 這種魯棒性的東西,該加仍是加上,儘可能不要假設前提。

結對編程與我的做業差別

最初,隆晉威同窗扮演駕駛員角色,趙瑞同窗扮演領航員角色。

在完成整個程序的框架後,分工完成模塊細節和測試,互相作駕駛員和領航員,在整個程序寫完後,一塊兒測試這個程序,並debug。

一我的用git很隨意,但是兩我的的話,就要提早看一下隊友的修改。

我的見解

結對編程過程當中,兩我的的做息一致性很重要,在剛寫完程序的時候,不出意外出了錯誤結果,咱們開始debug,主要的debug任務是在凌晨完成的。debug到晚上十二點,1000組數據跑對了,後來加到10000又出錯了,咱們又debug到1點,10000沒問題的時候,當時已經凌晨兩點了,若是兩我的有一個不習慣熬夜的話,這還真有點不舒服了,還好我倆都很不養生。

兩我的的debug的速度果真不是1+1=2的簡單加法,速度比一我的debug要快得多。

還有就是一塊兒工做在有進展的時候兩我的會一塊兒以爲很開心,分享一下喜悅,比一我的有進展本身心裏爽一下還happy,好比亮點debug完咱們覺得大功告成了就很開心(然而次日加大測試量又出現了新的錯誤樣例)。

結對編程過程當中學習的速度時迅速的,這一次結對編程我向隆晉威同窗學到了不少,好比代碼規範,GitHub的使用和visual studio code的使用,還有用腳原本測試程序。

會選擇結對編程用於解決部分任務。

工做時刻

1523806766472

代碼

 
  
  
  
  
相關文章
相關標籤/搜索