301
社区成员
发帖
与我相关
我的任务
分享
设计遵从递归下降的思想,Expr->Term->Factor->...,构建出了表达式树Expr后传入静态方法TransPoly,将表达式树转化成多项式Polynomial。Mono代表单项式,是多项式的一部分。
自我评价:
优点:类的建构比较清晰地体现了递归下降的思想,有比较强的可迭代性和内聚性,后续若要新增可以直接修改Mono类和新建新的因子。
缺点:部分类的复杂度较高,递归调用较多,代码量较冗余。

这张图显示了每个类中的代码行数和代码规模
总代码行数:1250
源代码行数:1018

可以发现我的Definer、Lexer、Polynomial类的复杂度较高,这是因为Definer是处理自定义函数的,涉及到了递归调用,Lexer是解析输入字符的,内部有多重if-else,Polynomial是多项式类,内部与Mono类的方法有很多互相递归调用,导致复杂度偏高。
OCavg(Average opearation complexity):平均操作复杂度
OCmax(Maximum operation complexity):最大操作复杂度
WMC(Weighted method complexity):加权方法复杂度

CogC:圈复杂度,表示程序中的独立路径数目。
ev(G):本质复杂度,表示程序中必须要有的控制流程数目。即,如果减少程序中任何一条路径,则程序将不完整。
Iv(G):内在复杂度,程序本质上的复杂度。表示程序在没有框架、库、编译器等支持时的复杂度。
v(G):程序体积,表示程序中的独立语句数目。
可以发现复杂度较高的方法有:
综上所述,复杂度较高的方法一般都是if-else层数较多或者设计较深的递归调用或者两个方法之间的相互调用。
三次作业简述:
读入一个包含加、减、乘、乘方以及括号(其中括号的深度至多为 1 层)的单变量表达式,输出恒等变形展开所有括号后的表达式。
第一次作业关键在于递归下降和确定基本项的思路。递归下降负责分析表达式中的结构,基本项思路负责去括号和化简。
递归下降理解:将一个表达式逐渐向低级形式分解,根据加减分出项,根据乘法分出因子,因子又下分为表达式因子,常数项因子,变量因子。
由于笔者在第一次作业时没有完全理解基本项的思路,于是没有单独建一个Mono(基本项)类。而是在Poly(多项式)类中用HashMap<Integer, Biginteger>来存储每个基本项,其中Integer代表x的幂次,BigInteger代表系数。并且在Poly类中提供了多项式加减乘的多种合并去括号化简的方法。
读入一系列自定义函数的定义以及一个包含幂函数、指数函数、自定义函数调用的表达式,输出恒等变形展开所有括号后的表达式。
第二次作业新增了嵌套括号,自定义函数和exp指数函数。
读入一系列自定义函数的定义以及一个包含幂函数、指数函数、自定义函数调用、求导算子的表达式,输出恒等变形展开所有括号后的表达式。
新添加三角函数因子sin,cos。
只需要新建一个三角函数因子,然后重写Mono的内部架构,改写Poly类中的加减乘乘方的方法即可。
在第二次作业中,我遇到了很多bug,发现很多都来自于深克隆和自定义函数转字符串处理的细节。
第二次作业,我对深浅克隆的认识太浅,以至于写的clone方法我以为是深克隆,但本质上却只是“部分深克隆”。比如:
M m = new M(this. , this. , this. );
return m;
这个就是典型的不稳定的深克隆,如果this.的内容都是Integer类或者String,那么这个m就是一个地址与原来地址完全不同的对象。如果this.的内容是自己定义的一个类的实例化(如this.mono),那么这个m和原来的对象的mono还是一个地址,仅仅实现了Integer和String基本类的深克隆,而自定义的类不会深克隆,故我称之为“部分深克隆”。
new方法只能深克隆Integer和String等基本类,而对自定义类没能力深克隆
所以要完全新建一个自定义类的实例,然后再用new方法。
我的自定义函数转字符串方法依托于每个因子重写的toString方法。所以toString的写法非常关键。而我忽略了表达式因子的括号,导致后续解析中报了许多问题。
第三次代码的问题在于解析求导因子的时候没有及时让词解析器lexer向后移一位。
本人分析他人bug采用的是同学开源的评测机,通过分析出错误的数据,从而判断该同学的错误。
我没有过多地考虑优化的问题,仅仅考虑了以下三点:
我的优化基本保持了原有架构不变,仅仅是改变了输出逻辑和输出后的字符串处理,所以不影响简洁性和正确性。但是由于笔者第一单元进行的比较艰难,对于优化的思考比较粗浅,算是一个遗憾吧。
在OO的第一单元,我深刻体会到了OO课程的强度,难忘第二次作业连写几天代码最后快到ddl发现代码的结构性问题,最后连夜重构还是以中测失败告终。 但是OO确实磨练了我的心智和时间规划能力,也让我清楚认识到敲键盘之前需要用手好好推演一下代码的架构是否可行。
第一单元的作业让我认识到:
也许可以给予一些视频层面上对于递归下降的讲解,可能会对初学者更为友好。
除此之外我觉得OO课程组的第一单元制作的十分优秀,节奏较难但可以跟得上。