天天看点

oo第一单元总结

当我在写这篇总结的时候,才刚刚从第三次oo作业中缓过神来。反观这三次作业,难度和功能都在递进,看起来难度比较大,特别是第三次作业,的确,如果使用面向过程的思想会让各部分耦合性大,比较复杂,但是如果应用面向对象的思想,将表达式中涉及到的元素归类处理,解决起来也是有迹可循。

Homework1

这一次作业是多项式求导,相对来说结构比较固定,可以枚举出来,按照不同的类型提取即可。

UML图

oo第一单元总结
oo第一单元总结

可以看出,在提取并计算导数和输出的时候复杂度较高,这也是此次作业难点所在,应该反思怎样进一步解耦。例如把提取系数、指数与计算导数分开,可以使复杂度降低,结构和功能更加明确和清晰。

分析自己程序的bug:在第一次作业中,中测强测互测均未发现bug。

关于互测:采用手动评测加自动评测的方式。手动评测是在原来测试自己代码的过程中构造的,主要是一些比较特殊的情况,例如1和-1的省略与不省略,前导0,这样比较特殊的处理,还有符号和空格等,比较有针对性,也比较高效,自动评测使用python随机生成表达式,主要优势是项数多,可以测评到比较大的数据,节约时间,但是针对性较差。

Homework2

这一次作业加入了sin(x),cos(x)和Wrong Format,我认为难点在Wrong  Format的判断和三角函数化简。

oo第一单元总结
oo第一单元总结
oo第一单元总结

在homework2加入了sin(x),cos(x)后,函数类型变得更复杂,于是将每一种类型都构造一个方法,可以看出每一种方法的复杂度不是很高。 

在优化方面存在很多不足,三角函数在化简时非常灵活,还可能存在递归化简这样的情况。在较短时间内我没有找到比较合适的化简方式,只能做一些基础的合并,导致性能分较低。

分析自己程序的bug:这次加入了非法格式的判断,由于非法格式的位置和形式比较灵活,出现了错判和漏判的情况。在强测中出现了\n这样的空白字符,但是我没有加以判断就直接用\s去掉了所有类型的空白字符,导致错误。我还出现了对三个正负号连用的判断错误,因为三个符号连用与我们数学习惯有一些不符,所以没有弄清楚三个符号加数字和三个符号加x/sin(x)/cos(x)的区别,导致错误。这种情况以后应该更加阅读指导书。

关于互测:由于上述的错误没有进入到互测。

Homework3

这一次作业允许递归嵌套,表达式分析求导比前面的作业复杂得多,难点有递归的处理,Wrong Format的判断,还要注意防止超时爆栈这样的情况。 

UML

oo第一单元总结
oo第一单元总结
oo第一单元总结
oo第一单元总结

在表达式结构层面,有三个类,表达式类、项类、因子类,将表达式按照“+/-”(需要注意跳过括号内)分为一个一个项,再将项按照“*”(需要注意跳过括号内)分为一个一个因子。在因子层面,有常数、x、sin、cos、表达式因子五个类,这样在处理表达式的时候就可以拆分为不同的类型进行相应的处理。在计算关系上设置了函数相乘的类,函数相加由于比较简单,并没有设置单独的类,而是将方法掺入了表达式和项的生成方法之中。这样其实在写的时候结构就比较清晰,从顶层向下写的时候不用太关注下层的具体实现问题,写起来也比较轻松。可以看出,没有太多过于复杂的类和方法。

分析自己程序的bug:在强测中漏判了Wrong Formet,cos(- 1)这样的形式,这个错误也是当初设计时偷懒导致的,因为没有找到很好的判断符号+空白字符+数字的方法,就把这种情况按在表达式不同的位置进行处理,但是没有想到cos(常数)这种情况,导致错误。在互测中,输出的时候忘记了表达式因子不能有指数这个规定,导致形式错误,导致bug。

关于互测:这次感觉搭建自动测评机在表达式生成这块过于灵活、规则也比较多,再加上写作业的时间较长剩下的时间不足,所以没有采取自动测评。在手动测评,我关注了像((((((((((1)))))))))) 这样多层括号是否会有超时爆栈的情况;sin(x**2)是否会因为化简变成sin(x*x)的错误;边界指数 这样易错的点,也有一些表达式比较复杂的,主要针对化简的正确性。

总结三次作业:

1. 正则表达式的灵活运用。正则表达式非常简洁方便,但是如果正则表达式过于复杂,贪婪模式的计算消耗也比较大,就可能会出现一些细节上的错误或者爆栈的情况。所以我们可以先将表达式化简或者分解再使用小的正则表达式。

2. 容器的使用。java提供了种类很多的容器,合理的使用可以让我们事半功倍,比如HashMap的使用可以帮助我们合并同类项,Arraylist的使用可以让我们灵活加减元素。

3. 注意程序的可扩展性,让自己的程序更加的工程化,可以结合模式的使用。

应用对象创建模式来重构

 这个单元学习了工厂模式,用来创建多个有一定共同特征的对象。我在这次作业中并没有使用这种模式,反思一下,我认为在创建常数、x、cos(x)、sin(x)、表达式因子这些类的对象时可以使用工厂模式,因为这些类都需要有求导操作和求这一个因子的表达式的操作,这两个方法可以在每个类中重写。重构时可以创建一个因子工厂,通过一些关键字来判断因子类型,创建不同的因子,在不同的因子类重写不同的求导和求表达式方法,返回表达式的底数字符串,表达式的指数,导数式的底数字符串,导数式的指数。

对比和心得

相比以前的编程题这次作业的难度大得多。通过这次作业,让我体会到面向对象思想相比于面向过程思想的优越性,我觉得面向对象编程可以使程序模块化,将有一定功能封装为一个类,在类中实现方法,管理相关数据,从而实现一定的功能。其他部分只需要将一个类所需要的参数传入,类再将其他部分所需要的结果传出,而忽略内部的其他数据,这样会使程序更加简洁。并且,模块化编程可以达到将一个复杂的问题一步一步分解,降低我们的思维难度,在一开始,我们只需要分析出需要什么样功能的类,而不需要把这个类怎么样实现这些功能都想清楚。面向对象编程的可扩展性更好,这次作业是在原来基础上不断扩展的,如果类与类之间耦合性低,类的可拓展性强,下一次作业只需要改动一些类增加功能即可,而不是牵一发而动全身。