BUAA_OO 第一單元總結
阿新 • • 發佈:2022-03-24
1.結構
1.1 大體思路
- 建立Term,Expression分別表示項和表示式;
- 建立Lexer,Parser解析表示式;
1.2 項 Term
- 筆者將項處理成形如axb∏sin(expi)cos(expi)
- axb :a--constant;b--exponent;
- ∏sin(expi)cos(expi):parameter整型陣列儲存三角函式型別,expression表示式陣列儲存參與三角運算的表示式
-
public class Term { private BigInteger constant; private BigInteger exponent; private ArrayList<Integer> parameter = new ArrayList<Integer>(); private ArrayList<Expression> expression = new ArrayList<Expression>(); }
1.3 表示式 Expression
- 筆者將表示式處理成∑termi形式,通過Term類陣列儲存各個項
-
public class Expression { private ArrayList<Term> expression = new ArrayList<>();}
1.4 詞法分析 Lexer
- 筆者認為可將每一次運算簡化成 expi?/num? [+/-/*/**/sin/cos] expi/num?
- 建立lexer處理運算表示式expi,運算數num,運算子
- 處理運算表示式:構建String類expression1和expression2儲存表示式,作為hashmap的key,並傳入Parser進一步解析
- 處理運算數:筆者在此模組將運算數與表示式視作一類,儲存入expression1和expression2中,傳入Parser進一步解析
- 處理運算子:筆者將運算細分成取反(neg),正弦(sin),餘弦(cos),加(add),減(sub),乘(*),乘方(**),取正(pos);將八類運算按Lexer-Parser運算子表解析,用整形parser表示,傳入Parser進一步解析
-
運算 parser值 neg 1 sin 2 cos 3 add 4 sub 5 mul 6 pow 7 pos 8 -
public class Lexer { private String curline; private String name; private String expression1 = "1"; private String expression2 = "1"; private int parser;}
- 建立hashmap<String,Expression>,以Lexer傳入的expression1,expression2為key,以解析表示式類作為value
- 通過Lexer傳入的整形lexer進行表示式或數的運算
-
public class Parser { private Lexer lexer; private HashMap<String, Expression> map; public Parser(Lexer lexer, HashMap<String, Expression> map) { this.lexer = lexer; this.map = map; }
2.演算法
2.1 大體思路
- 逐層運算:將表示式之間的複雜運算逐層解析成項之間的簡單運算
2.2 表示式運算
- 筆者將表示式的運算分成:加(add),減(sub),乘(*),乘方(**),正弦(sin),餘弦(cos)六類
- 加(add):由於筆者以Term陣列表示表示式,故表示式的相加可通過Term陣列相加實現,在此不再贅述
- 減(sub):需要將作為減數的表示式取反,可通過將Term陣列中的所有Term取反實現,其餘與加法相同
- 乘(*):需要遍歷表示式的Term陣列,將表示式乘法轉化成若干Term相乘,最後將結果相加
- 乘方(**):可視作若干次表示式與自身的乘法,不再贅述
- 正弦/餘弦(sin/cos):表示式進行該運算後降級為Term類,儲存入新建Term的三角部分
2.3 解析方式
- 通過整形parser值來表示運算方式,parser值在Term,Expression,Lexer,Parser類內通用
- 筆者將運算細分成表示式之間,運算數之間,表示式與數之間三種情況。在解析前先判斷Lexer傳入的String類表示為expi或num
2.4 項運算
- 筆者將項的運算分成:加(add),減(mul),乘(*),乘方(**),取反(neg),取正(pos),正弦(sin),餘弦(cos)
- 由於項的運算相對簡單,筆者不再贅述
3.細節
3.1 UML類圖
3.2 度量分析
可以看出,在Parser類的next()複雜度過高,原因是該函式是解析表示式的主函式。所以筆者的解析方式並不巧妙,以後會盡量改進優化。
3.3 化簡
筆者對於化簡的做法較為簡單,僅實現了表示式的合併同類項,sin0=0,cos0=1,對於二倍角公式,sin2x+cos2x=1等三角恆等式沒有過多涉及,以後會盡量改進優化
3.4 bug修復
筆者在評測過程中遇到了一下bug:
-
-
- Term的係數constant的資料型別過小(Integer),計算時容易出現溢位,後改為BigInteger解決
- 程式無法處理形如sin(1)的項,後發現將1等運算數視為項導致出錯,應將其視作表示式
- 計算乘方時沒有考慮0次方情況,導致出錯
- 程式無法處理形如+1,+x等表示式,後發現java內建函式無法將其直接轉化,應特判正號
-
4.總結
在本單元oo作業中,筆者深刻理解了面向物件的理念,並且深入熟悉了java語言,希望在以後的學習過程中可以不斷進步,少些bug!