面向对象第一单元总结

第一单元作业(表达式求导)总结

一、程序结构的分析

第一次作业:

·类图

面向对象第一单元总结_第1张图片

 

 

·复杂度

面向对象第一单元总结_第2张图片

  第一次作业在现在看来还是比较简单的,要求实现对简单的幂函数多项式进行求导。但是由于自己之前没有系统的学习过java,再加上之前也基本上没有使用过正则表达式,所以基本上是边写代码边学java的状态。为了能够应用正则表达式简便快速地处理字符串,我在正则表达式的学习和应用上面花费了很长时间。在处理好字符串的解析工作后,第一次作业剩余的工作就比较简单了。建立一个Computepoly类用于存储多项式,一个poly类用于存储多项式中的每个项,然后依次完成求导,输出等工作。

  第一次作业的优化部分主要分成3部分:

    (1)对于同类项的合并:在解析字符串生成表达式的同时完成的

    (2)针对系数为+1,-1以及指数为0的情况进行优化:输出结果时进行

    (3)尽可能将正项提前:1-x比-x+1长度短,针对Poly类实现一个CompareTo接口,然后再调用Collections的Sort方法实现自动排序

面向对象第一单元总结_第3张图片

 

 

 

第二次作业:

·类图

面向对象第一单元总结_第4张图片

 

·复杂度

面向对象第一单元总结_第5张图片

面向对象第一单元总结_第6张图片

 面向对象第一单元总结_第7张图片

   第二次作业是在第一次求导作业的基础上增加了三角函数sin(x)和cos(x)的求导。在输入的处理上,我依然采用了用一大长串正则匹配输入的方法。然后再用正则分割匹配表达式中的每一个项,每个项采取类似三元组的形式去存储并求导。

  第二次作业的架构是先用一个ployclass对象去存储和解析读入的多项式,然后在polyclass对象的内部创建若干个monomialclass对象去存储和解析多项式的每个项。每个monomialclass对象都是由constclass,sinclass,cosclass,powerclass四个对象构成的,这样做能够使程序有更好地层次结构。

  对于求导结果的存储,我选择了HashMap,其中key值由sin、cos、x的次数构成,value值为系数,利用HashMap可以直接实现同类项的合并。在合并完同类项后,我认为用三角函数的相关公式去进一步化简有些复杂,所以没有再进一步化简。

  

第三次作业:

·类图

面向对象第一单元总结_第8张图片

 

·复杂度(截取了部分)

 面向对象第一单元总结_第9张图片

   第三次作业在第二次作业的基础上,支持了三角函数内的括号嵌套。嵌套规则的出现对读入字符串的解析和判断带来了很大的不便。由于之前两次作业我均采取的是用一个超长的正则表达式去匹配读入的字符串,所以第三次作业我依然想这样做。但是尝试了一段时间后发现,由于括号嵌套的层数和括号嵌套的内容都不确定,无法再用一个超长的正则表达式去一次匹配和解析完读入的字符串,只能采取边解析、边创建、再解析、再创建的策略,即采取逐层解析、逐层判断的策略。

  第三次作业的架构与第二次作业的架构比较相似,最大的不同在于每个项对象,每个sin对象,每个cos对象的括号内都有可能是一个新的多项式对象,这样整个关系图就形成了一个环。所以在处理字符串时,需要根据读到的实际内容去判断应该新建一个什么样的对象。当读到括号内嵌套的内容时,直接在当前对象中以字符串的形式存储下来,以便合成求导的结果返回。

  在具体处理括号嵌套的问题时,我才用的是类似栈结构的方法去处理的,比如读到第一个“(”后计数为1,然后开始向后扫描字符串,每扫到一个“(”,计数+1,每扫到一个“)”,计数-1。直到计数为0时,就找出了最外层括号嵌套的内容,并把内层的字符串再次调用字符串解析程序分析成分。在处理字符串的同时,完成对WRONG FORMAT!的判断。

  在实现求导的功能以后,我没有做复杂一些的优化处理,只是在打印结果的时候做了一些输出上的优化。

 

二、出现的bug及如何找bug

  第一次作业中,在公测和互测中没有被找出bug。

  第二次作业中,在公测和互测中没有被找出bug。

  第三次作业中,在公测和互测中出现了bug,出现bug的地方有两处。

  第一处是我在输出时忘记了对数据格式的检查和修改,在对cos()^负指数求导时,返回的结果可能会出现x*--5*cos().....的情况,这种情况是不符合格式要求的,针对bug的修复是在输出之前统一对"++","+-","-+","--"替换成等价的“+”和“-”。这样解决了输出不符合格式要求的情况。

  第二处bug是自己的变量名引用错了。。。我在解析表达式的时候,对第一项做了处理,例如对于 + - x*x + sin(x), 我会先变成 -1*x*x + sin(x)再处理,处理前的字符串为expTmp,处理后的字符串为exp。结果码着码着就给码晕了,后面有几处引用成原始的expTmp了。这会引发求导错误,数据越界等各种错误。。。导致自己在强测挂了一个点,互测被刀了20多刀。。。 

  第三次作业在完成功能后并没有做充分的测试,导致自己程序在进行强测和互测时出现了一些错误,为自己的懒惰付出了代价,在以后的作业中要多进行测试。

  在互测环节中我采取的是比较原始的测试方法,手工构造一些可能的坑点,比如指数为0,系数为0,-1,1这种的测试样例等等。这种找bug的效果并不好。在公开测试样例后,我发现很多测出bug的测试样例单靠凭空构造样例去碰运气是很难构造出来的。找到别人程序bug的最好办法还是认真地去阅读别人的代码,从逻辑上找出别人的错误,这点还是需要自己去改正和学习的。

 

三、关于面向对象的使用与思考

  在第一次作业中,刚接触面向对象式的程序设计,虽然自己尝试去用面向对象的思想完成求导作业,但是最后还是创建了一个类,在类里面来回来去的调用函数。第一次作业完成以后,还是没能感觉出和之前用C语言编程有多大的区别。

  在第二次作业中,由于新增了三角函数类,想要在一两个类中完成所有任务就有些困难了。在这次作业中,我把输入的字符串逐层分隔,从多项式类到单项式类,再到单项式中的三角函数类,幂函数类,常数类。在每一层级中,实现其相应的功能,将求导这个任务一层层的分解。在这次作业中,初步地用到了一些面向对象的思想。但由于因子类中存在着大量复制粘贴的相似代码,所以程序看起来有些臃肿。

  第三次作业中,在第二次作业的基础上尝试使用了一些简单的接口,比如把项和各种因子的求导方法通过一个接口来实现。这样能够使类之间的关系更加清晰并且减少程序中一些重复代码的出现。

四、对比和心得体会

  通过阅读同学的优秀代码,我发现他们都有一个的特点,那就是他们面向对象的思想用的非常好,类和类之间耦合度低,组织更加高效。反观自己的代码,类与类之间的协作并不好,存在大量Ctrl+C、Ctrl+V的地方,有许多需要改进的地方。

  总体来说,由于本学期是我第一次接触java语言和面向对象,在类的继承和接口实现等方面还有许多需要学习和练习的地方,并且自己的编程能力还有待进一步提高。希望自己在接下来的课程中能够更加熟练地应用java语言并且更好地把面向对象的思想应用于编程中。

 

你可能感兴趣的:(面向对象第一单元总结)