OO1-3次课下作业总结

OO第一单元总结

整体总结

OO课程的第一单元作业主题是第1到3次作业,内容是尽可能多的拆括号并化简表达式。我在假期里并没有预习任何面向对象的知识,也没有学习git等工具的使用,更没有配置IDEA、eclipse等编辑器的Java环境,在刚开学就近乎于期末的高压下,我这三周过的很痛苦,但是也收获了非常多的知识和面向对象编程的思想和方法。在第一周,我主要是进行配置环境,学习git的使用,pre2前三个task的学习,但是由于我对时间规划的不合理,我并没有及时完成第一周的作业,中测有3个测试点没有过,而且用了很多的static函数,更像是在完成一个面向过程的编程任务。在第二周,我在同学的帮助下,理解了递归下降的拆括号方法,还在强生同学的帮助下,认识了Hashmap容器,成为了我第二次作业基本项的一部分。第二周是最痛苦的,因为我第一周的作业基本上是面向过程,所以我第二周必须要重构代码,在递归下降的返回值问题上,我思考了很久,最后也是在同学的帮助下,把返回改成void类型,对我递归下降的思路帮助很大。在第一周和第二周,我把pre2和pre3前四个task做完了,学习了正则表达式等知识,在我重构代码的过程中,我感受到了面向对象编程的魅力所在——不需要重复造轮子,大大减少了代码量。由于我在第二周对代码进行了重构,并且支持多层括号的拆分,在第三周的作业中我需要改动的部分比较少,因此对我来说第三周是比较轻松的。在对自定义函数和三角函数内部进行迭代之后,代码总体上可以正常运行。总结一下,OO课程在第一个月就让我压力报表,但是我学到的知识确实值得我付出的努力和艰辛。

个人架构分析

我采用了递归下降的方法,一个Expr由多个Term加减得到,一个Term由多个Expr相乘得到,经过自定义函数替换、求和函数替换、去空白符、拆乘方、去前导零、化简连续加减等预处理之后,表达式作为一个Expr传入,把它拆分成多个Term相加。此时需要判断Term是否为最小项(常数、x、sin()、cos()),如果不是最小项,则需要把这个Term拆分成多个Expr相乘;如果是最小项,则需要把这个Term转化为一个基本项,储存在Term的Variables属性里。每一个Expr和Term都有一个ArrayList,在这里我定义为Variables,我们计算Expr的方法是把这个Expr拆分出的所有Term的Variables相加减;计算Term的方法是把这个Term拆分出的所有Expr的Variables相乘。在这样的递归下我们就能获得最顶层Expr的Variables,再把得到的Variables翻译成表达式即可。

对此设计我们也可以进行一些优化,比如我们可以在把最终的Variables翻译成表达式之前进行合并同类项操作,这样可以缩短表达式长度。在第三次作业中题目要求化简三角函数括号里的表达式因子,我们可以遍历得到的表达式,把所有三角函数内部的表达式因子以同样的方法进行化简。我很还可以利用sin(x)2+cos(x)2=1的性质,把所有的cos(x)2转化成1-sin()2,这样也有利于化简。同理也可以使用二倍角公式等三角函数知识进行化简,在这里不再赘述。化简的方法有很多,只要肯花时间一定能拿到很高的性能分。在我的代码中仅仅做到了合并同类项这一步。

类图描述

在实现过程中,我使用Factor接口作为Term,Expr和Variable这三个大类的统一接口,目的是可以用一个ArrayList将不同类的数据集中起来,方便处理。Custom类是用来替换自定义函数的类。我处理sum函数的方式是在Mainclass里用static函数处理。

优点:类数量比较少,思路更加清晰。

缺点:使用大量的static函数,整体结构不够精巧,面向过程痕迹比较重。

度量分析

Complexity metrics
Method CogC ev(G) iv(G) v(G)
Custom.Custom(String) 1 1 2 2
Custom.getName() 0 1 1 1
Custom.getValue() 0 1 1 1
Custom.getVars() 0 1 1 1
Expr.Expr(String) 0 1 1 1
Expr.calVariables() 1 1 2 2
Expr.findNextAddOrSub(String) 9 3 7 9
Expr.getFinalvalue() 41 10 14 17
Expr.getTerms() 11 1 9 11
Expr.getVariables() 0 1 1 1
Expr.merge(ArrayList) 7 1 6 6
Expr.removeAddOrSub(String) 13 1 8 11
Mainclass.calfinaladdstr(String, int) 7 1 1 4
Mainclass.findNextComma(String) 6 5 5 6
Mainclass.findbracket(String) 6 3 3 5
Mainclass.findinversebracket(String) 6 3 3 5
Mainclass.getParas(String) 6 1 6 6
Mainclass.main(String[]) 1 1 2 2
Mainclass.needcontinue(String, int) 7 2 7 8
Mainclass.pre1(String) 2 1 3 3
Mainclass.pre2(String) 26 6 11 11
Mainclass.replaceAllCustoms(String, ArrayList) 1 1 2 2
Mainclass.replaceCustom(String, ArrayList) 42 8 14 14
Mainclass.replaceSum(String) 17 1 6 8
Mainclass.replacetrig(String) 7 3 3 3
Term.Term(String) 2 1 2 3
Term.calVariables() 7 1 5 5
Term.findNextMulti(String) 7 3 4 6
Term.findinversebracket(String) 6 3 3 5
Term.getExpr() 0 1 1 1
Term.getExprs() 11 1 6 7
Term.getFinalvalue() 39 10 12 15
Term.getSignal() 0 1 1 1
Term.getVariable() 14 1 9 10
Term.getVariables() 0 1 1 1
Term.isMininum() 6 4 5 6
Term.merge(ArrayList) 7 1 6 6
Term.multiVariable(Variable, Variable) 4 1 5 5
Term.multiVariables(ArrayList, ArrayList) 3 1 3 3
Term.setExpr(String) 0 1 1 1
Term.setSignal(boolean) 0 1 1 1
Variable.addcos(String, int) 2 1 2 2
Variable.addsin(String, int) 2 1 2 2
Variable.getCoefficient() 0 1 1 1
Variable.getCoss() 0 1 1 1
Variable.getExponent() 0 1 1 1
Variable.getSins() 0 1 1 1
Variable.setCoefficient(BigInteger) 0 1 1 1
Variable.setCoss(HashMap<String, Integer>) 0 1 1 1
Variable.setExponent(int) 0 1 1 1
Variable.setSins(HashMap<String, Integer>) 0 1 1 1

在这里我们可以看见,Cogc值比较高的方法集中在对表达式的预处理和Variables的翻译过程,这两个部分都是进行了字符串和类的形式转换,所需工作量比较大。

Class OCavg OCmax WMC
Custom 1.25 2 5
Expr 5.25 16 42
Mainclass 4.85 12 63
Term 4.25 15 68
Variable 1.2 2 12

个人bug总结

第一次作业:由于我的第一次作业没有通过中测,出现的bug比较多,在这里我总结出比较严重的一个bug——系数应该使用BigInteger类型存储,我使用的是int类型,导致第七个数据点溢出。

第二次作业:由于我在第二次作业重构了代码,因此出现的bug也比较多。一、在Expr的Variables翻译成表达式字符串时,若某一项系数为0,我会在原有基础上补充一个空字符串。但是我在判断首位是否为正好时,使用了indexof(0),导致空串数据越界。这个bug出现频率很高,被很多人hack到了。二、在提取项中间的正负号时,没有考虑到三角函数内的正负号不应该被提取,把sin(-1)提取成了-1*sin(1),虽然这种情况下是正确的,但是遇到平方或者cos()就会出错。

第三次作业:由于第三次作业中的自定义函数和求和函数更加复杂,但是我并没有更新这两部分的替换机制,出现了两个bug。一、sum函数中替换i应该加上括号,如sum(i, -1, 1, sin(i**2))。二、自定义函数出现的x被替换的问题。比如

2
f(x, y) = x**2 + (y + 2)**2
g(z, x) = cos(z) + 8*x
f(f(sin(x), 1), g(2*x, f(x, 2)))

//以下是bug出现过程
在计算g(2*x, f(x, 2))时,把cos(z) + 8*x中所有z换成2*x,转化成
cos(2*x) + 8*x
再把cos(2*x) + 8*x中所有x转化为f(x, 2),转化成
cos(2*f(x, 2)) + 8*f(x, 2)
很明显不应该把cos(2*x)中的x替换成f(x, 2)

学习心得

首先,我在这一个月深刻意识到了假期预习的重要性。在第一周的周二,我还在配置IDEA的Java环境,学习git的使用;周三我完成了pre2task1;周四我完成了pre2task2;周五上午我完成了pre2task3,晚上才开始写作业。第一周的进度非常赶,导致我最后差2个小时完成作业。这第一周的生活给了我深刻的教训,一定要在假期预习。其次,我认为OO课程组提供的指导书和廖雪峰的官网都是质量很高的教程,不需要在b站上走弯路。最后,我想说说我在这三次作业中的感受。过低的能力或过高的要求都会给我很大的压力,但是在压力下学习效率会比较高,能学到真正有用的知识也会更多。总而言之,在学习过程中越轻松,能学到的东西就越少;越是精神肉体的双重折磨,越是能激发人的潜能。

posted @ 2022-03-25 22:09  Albert_ZYT  阅读(45)  评论(0编辑  收藏  举报