BUAA_OO_第一单元总结

虞家洲-20377049 学生 2023-03-19 21:43:47

第一次作业

构造思路:

       在第一次作业中,我尝试使用某种“统一”的,单一的表达方式在不同的运算处理中传输,最终选定的表达方式是Array List<Hashmap<Integer,BigInteger。Integer储存字母因子的ASC码,或者为0,表示这一因子为系数。BigInteger储存字母因子的次数或者是系数的大小,组合为Hashmap构成一个项,多个项以ArrayList储存构成表达式。用Operater接口来实现各个运算的具体方法。Operater中必须要有以运算符号为分割两端的表达式的具体结果。

       在对表达式的解析上,我认为词法解析单独写一类没有特别的意义,找到各个运算符的具体位置即可。对于表达式解析采用递归下降的方法,首先将所有以在括号外的加减为分割多项式,进一步以括号外乘法为界限分割多项式,然后以指数运算符分割,再以加减分隔,最后以乘法分割,最终达到一个要么是数字,要么是字母的分割结果。

uml类图:

 复杂度分析:

MethodCogCev(G)iv(G)v(G)
Add.Add(Operator, Operator)0111
Add.check(HashMap<Integer, BigInteger>, HashMap<Integer, BigInteger>)147711
Add.getResult()9455
Exp.Exp(Operator, Operator)0111
Exp.getResult()3641616
MainClass.main(String[])16177
Mul.Mul(Operator, Operator)0111
Mul.getResult()2011010
Nom.Nom(String)3133
Nom.getResult()0111
Operator.Operator(Operator, Operator)0111
Operator.getLeft()0111
Operator.getResult()0111
Operator.getRight()0111
Parser.Parser()0111
Parser.findAddOrSub1(String)11437
Parser.findAddOrSub2(String)4334
Parser.findExp(String)4334
Parser.findMul(String)11448
Parser.findMul2(String)4345
Parser.parse(String)3133
Parser.parse1(String)7333
Parser.parse2(String)3222
Parser.parse3(String)3222
Parser.parse4(String)7333
Parser.parse5(String)3222
Sub.Sub(Operator, Operator)0111
Sub.check(HashMap<Integer, BigInteger>, HashMap<Integer, BigInteger>)147711
Sub.getResult()10466
     
ClassOCavgOCmaxWMC 
Add4.33713 
Exp7.51415 
MainClass777 
Mul4.589 
Nom234 
Operator114 
Parser3.08637 
Sub4.67714 
     
Packagev(G)avgv(G)tot  
 4.21122  
     
Modulev(G)avgv(G)tot  
oohomework_2023_20377049_hw_14.21122  
     
Projectv(G)avgv(G)tot  
project4.21122  

反思:

       这样的构造并不能体现抽象和层次化,通过这样的大一统的方式来储存所有的表达式,表达式中不可能再储存表达式的,使得对于后期作业三角函数的储存变得几乎不可能实现,没有体现面向对象的思想。同时在具体的函数上,由于多次的对ArrayList和Hashmap的遍历,使得时间复杂度大量上升,可以轻而易举得出这个结构是不好的结构。在函数的运算上,为了克服深浅拷贝的问题,我每一次都新声明了一个变量,尽量通过改变和返回新的变量来避免对原容器内容的修改,创造了一些冗余的储存。

第二次作业

构造思路:

       对于如何储存表达式、项、因子,我的第一次作业的储存结构完全不能迭代使用,故对这一部分进行了完全的重构,随之对于运算类进行了与之适配的小幅的重构,而语法解析的重构则几乎保留,改写相对容易。

       在新的表达式储存容器,我采取的方式是:接口Factor implement四个类Expr(表达式)、Term(项)、Var(字母因子)、Tri(三角函数因子)。Factor接口要实现两个函数,get()函数返回Hashmap<Factor,Biginteger>,equal(Factor)函数返回两个factor是否相同的boolean。Expr的Hashmap<Factor,Biginteger>储存term的系数,term的Hashmap<Factor,Biginteger>储存因子到次数,Var的Hashmap<Factor,Biginteger>中,Factor为Term类用于标志此为字母因子,Biginteger储存字母因子的asc码,Tri的Hashmap<Factor,Biginteger>中,Factor为Expr类,储存三角函数内部的表达式,Big integer用来标识三角函数的sin/cos;对于每一个类中的equal()都要同时比较两个factor的Hashmap<Factor,Biginteger>的相同与否,也就是比较Hashmap<Factor,Biginteger>中的Factor是否相同,Biginteger是否相同将表达式进而一步步落到字母的比较,对于三角函数的内部expr的比较最终也会调用Expr中定义的expr最终达到统一。然后利用equal()来实现同类项的合并。

       对于自定义函数,储存每个函数输入的表达式的f、g、h作为function类的symbol,对被解析的项调用的函数比较他们的symbol来确定调用的函数,同时在function类中储存字符替换后的String表达式,当具体函数调用时,利用String的replace方法将因子进行替换,然后再进行词法解析,带入原函数。

uml类图:

复杂度分析:

MethodCogCev(G)iv(G)v(G)
Add.Add(Expr, Expr)0111
Add.get()2133
Exp.Exp(Expr, Expr)0111
Exp.get()2141111
Expr.Expr()0111
Expr.addTerm(Factor, BigInteger)4344
Expr.equal(Factor)189711
Expr.get()0111
Expr.toString()3133
Generate.Generate(String)3133
MainClass.main(String[])1122
Mul.Mul(Expr, Expr)0111
Mul.get()9155
Parser.Parser(ArrayList<function>)0111
Parser.findAddOrSub1(String)11437
Parser.findExp(String)11437
Parser.findMul(String)11448
Parser.parse1(String)7333
Parser.parse2(String)3222
Parser.parse3(String)3222
Parser.parse4(String)1271010
Sub.Sub(Expr, Expr)0111
Sub.get()2133
Term.Term()0111
Term.addFactor(Factor, BigInteger)4344
Term.equal(Factor)189711
Term.get()0111
Term.toString()3133
Tri.Tri(Expr, String)2122
Tri.equal(Factor)7444
Tri.get()0111
Tri.toString()5144
Var.Var(Character)0111
Var.equal(Factor)7434
Var.get()0111
Var.toString()0111
function.findComa(String)3133
function.function(String, Character)0111
function.get(String, ArrayList<function>)1122
function.getSymbol()0111
generateFunction.findEaqual(String)3323
generateFunction.generateFunction(String)0111
generateFunction.get()0111
     
ClassOCavgOCmaxWMC 
Add234 
Exp61112 
Expr3.6918 
Generate333 
MainClass222 
Mul356 
Parser4.25834 
Sub234 
Term3.6918 
Tri2.75411 
Var1.7547 
function1.7537 
generateFunction1.6735 
     
Packagev(G)avgv(G)tot  
 3.28141  
     
Modulev(G)avgv(G)tot  
homework_23.28141  
     
Projectv(G)avgv(G)tot  
project3.28141  

反思:

       更新了架构使得三角函数的储存变得轻松,整体的层次得以体现,代码初步具有了面向对象的思想。对于自定义函数的具体储存和返回值总是通过字符串来进行,显得相对笨拙,但是较为直观,易于理解。在各个具体实现Factor的类中分层次实现equal()方法,使得运算和化简变得简单,实现这个代码也相比于不分层变得更加简单。

第三次作业

构造思路:

       相对简单,新加入了一个Derive类来实现函数的求导,具体的实现也较为简单,故不赘述。

uml类图:

复杂度分析:

MethodCogCev(G)iv(G)v(G)
Add.Add(Expr, Expr)0111
Add.get()2133
Derive.Derive(Expr, Character)3811414
Derive.get()0111
Exp.Exp(Expr, Expr)0111
Exp.get()2141111
Expr.Expr()0111
Expr.addTerm(Factor, BigInteger)4344
Expr.equal(Factor)209913
Expr.get()0111
Expr.toString()3133
Function.Function(String, Character)0111
Function.findComa(String)3133
Function.get(String, ArrayList<Function>)1122
Function.getSymbol()0111
Generate.Generate(String)3133
GenerateFunction.GenerateFunction(String)0111
GenerateFunction.findEaqual(String)3323
GenerateFunction.get()0111
MainClass.findComa(String)3133
MainClass.findEaqual(String)3323
MainClass.funcClean(String, ArrayList<Function>)1122
MainClass.main(String[])1122
Mul.Mul(Expr, Expr)0111
Mul.get()9155
Parser.Parser(ArrayList<Function>)0111
Parser.findAddOrSub1(String)13459
Parser.findExp(String)11437
Parser.findMul(String)11448
Parser.isNumber(String)3323
Parser.parse1(String)7333
Parser.parse2(String)3222
Parser.parse3(String)3222
Parser.parse4(String)1691515
Sub.Sub(Expr, Expr)0111
Sub.get()2133
Term.Term()0111
Term.addFactor(Factor, BigInteger)4344
Term.equal(Factor)189711
Term.get()0111
Term.toString()3133
Tri.Tri(Expr, String)2122
Tri.equal(Factor)7444
Tri.get()0111
Tri.toString()5144
Var.Var(Character)0111
Var.equal(Factor)7434
Var.get()0111
Var.toString()0111
     
ClassOCavgOCmaxWMC 
Add234 
Derive6.51213 
Exp61112 
Expr3.6918 
Function1.7537 
Generate333 
GenerateFunction1.6735 
MainClass2.5310 
Mul356 
Parser4.331039 
Sub234 
Term3.6918 
Tri2.75411 
Var1.7547 
     
Packagev(G)avgv(G)tot  
 3.59176  
     
Modulev(G)avgv(G)tot  
oohomework_2023_20377049_hw_33.59176  
     
Projectv(G)avgv(G)tot  
project3.59176  

反思:

       由于对于不同因子的求导,如三角函数因子和字母因子的求导方式并不同,但我只写了Derive类,在其中加入了很多if判断,使得此类成为一“巨类”,是需要后续改进的,可以考虑将derive分别写入不同的类中,使得层次更加分明,避免出现这样的“巨类”。

总结:

       经过了这三次的迭代作业,有这样几个经验,首先是层次化和抽象很重要,不要尝试用大一统的方式去解决和表示所有的问题,简单的分层和抽象可以让计算机自己去处理复杂的数据结构中有关索引的部分。其次是在第一次的作业时,就要尽量去思考如何为之后的迭代做准备。一个好的架构远比具体写出代码重要得多。

 

...全文
47 1 打赏 收藏 举报
写回复
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复

由于对于不同因子的求导,如三角函数因子和字母因子的求导方式并不同,但我只写了Derive类,在其中加入了很多if判断,使得此类成为一“巨类”,是需要后续改进的,可以考虑将derive分别写入不同的类中,使得层次更加分明,避免出现这样的“巨类”。


可以通过重构来改进

相关推荐
发帖
2023年北航面向对象设计与构造

382

社区成员

2023年北京航空航天大学《面向对象设计与构造》课程博客
java 高校 北京·海淀区
社区管理员
  • 被Taylor淹没的一条鱼
  • 柠栀_Gin
加入社区
帖子事件
创建了帖子
2023-03-19 21:43
社区公告
暂无公告