BUAA OO课程第一单元总结

张翼飞-22230622 学生 2024-03-20 10:54:10

目录

 

第一次作业

程序结构及复杂度

架构设计及性能优化

Bug

第二次作业&第三次作业

程序结构及复杂度

架构设计及性能优化

Bug及速度提升

心得体会

未来方向


第一次作业

程序结构及复杂度

UML类图如下:

 

用varFactor,exprFactor,Number来实现Factor这个接口,Term类的属性是储存Factor的容器,而Expr类的属性是储存Term的容器,Poly类是Expr.cal()的结果。详情见下文架构设计

方法复杂度如下:

 

可见这次作业的复杂度比较低,易于维护和测试

类复杂度如下:

 

架构设计及性能优化

在本次作业中,作业要求读入一个包含加、减、乘、乘方以及括号(其中括号的深度至多为 1 层)的单变量表达式,输出恒等变形展开所有括号后的表达式。其实本次作业最难的是要理解递归下降的思想,当时理解了好一会,才算是搞明白了。简单来说就是在解析表达式的时候就认为解析项的方法已经写好了,去调用它来解析表达式,同理在解析项的时候假装认为解析因子的方法写好了,就这样一步步拆解下降到最简单的结构——因子,然后写每种因子的解析方法,这其中解析表达式因子就会重新回到解析表达式在一步步下降到因子。这么做也就很方便地把表达式解析完了。

第二难的地方就是如何计算,这个也会影响后面的迭代,所以在和同学的讨论后我选择了新建一个Poly类,每个类有一个类似toPoly的方法,同样也是利用了递归的方法将表达式转换为了多项式,然后在多项式类里进行加减乘的运算。这样做也比较方便我后续的迭代。

最后麻烦的地方是将最终的多项式变为字符串,需要写一个toString方法,不过这个也就是麻烦一点,考虑的情况多一点,需要根据系数和指数的大小来判断数字省不省略,乘号加不加之类的问题,最特别的一点是在这里我将系数里大于0的一项提到最前面来优化性能,防止开头一个负号多一个字符。

Bug

这次作业因为较为简单,没什么特别的要求,所以在互测时也没有发现bug,强测也获得了100分,就不多说了。

第二次作业&第三次作业

程序结构及复杂度

加了导数因子(DxFactor)和自定义函数因子(FuncFactor)来实现Factor接口,Function类用来表示输入中的函数表达式,Index类用来表示变量因子的指数和指数因子的指数,一起作为Poly类中基本项的key。详情见下文架构设计。

方法复杂度如下:

由于第一次作业奠定了好的基础,最后的复杂度并没有上升多少,还是易于维护与复用。

类复杂度如下:

 

架构设计及性能优化

为什么将这两次作业放在一起,因为第三次作业加的东西不多,觉得没必要还单独说,而且两次作业也都涉及到了自定义函数,放在一起说也能体现迭代。

首先第二次作业的要求是读入一系列自定义函数的定义以及一个包含幂函数、指数函数、自定义函数调用的表达式,输出恒等变形展开所有括号后的表达式。在这次作业中加入了两个麻烦的东西,一个是自定义函数,一个是指数函数。先说自定义函数,我首先考虑的是在哪里处理自定义函数,是要预处理,还是看作一个因子,在计算的时候再展开,最后觉得预处理太麻烦,并且可扩展性不好放弃了。所以新建了一个Funcfactor类再在这个类的计算方法(就是toPoly)里展开为表达式,再返回表达式的计算结果,这也是利用了递归的思想。

至于指数函数,只有先想好这次的计算方法才能开始处理指数函数。在听取了研讨课上同学的建议以及舍友的讨论后,决定把最后结果的基本项定为系数×x的a次方×e的b次方,而这里的a和b就是Poly类的key,取名为index,所以我就新加了一个类,他有两个属性,一个是x的指数,一个是e的指数。这样处理后思想其实就和第一次作业很像,但比较不同的是此时比较指数时得比较e的指数的大小,这个时候需要在index类里重写compareTo方法,因为e的指数为多项式,所以比较时就先转换为字符串再比较。

在性能方面,此次作业就可以有各种大佬来卷性能,因为可以把e指数里的因子提出来缩短长度,但我就只做了两个处理,没去提因子。第一个处理就是第一次作业中的将正的项提到最开头,第二个处理就是删去e里不必要的括号。我是用正则表达式匹配来处理e里面如果只是数字或变量因子就只有一层括号,而里面是一个指数因子的情况稍微复杂一点,不仅要有正则表达式,而且还要用括号匹配来判断是不是只有一个指数因子,这样做就会去掉很多括号,优化了性能。

最后是第三次作业,这次作业因为有前两次作业良好的基础,所以加的东西很少,新建一个导数因子的类,在Poly类加一个求导的方法,只需实现基本项的求导即可,不麻烦,分几种情况就可以。这次也顺利地通过了。

Bug及速度提升

而在第二次作业我在强测中错了一个点,是TLE,我发现是我在多项式计算时没有先把系数为零的项去掉,导致计算时一堆系数为0的项相乘浪费了太多时间,删去后就能顺利通过了。还有一个重要的提升速度的方式,因为我在很多地方需要用到字符串,所以导致调用了太多toString方法,所以我让string成为多项式的一个属性,只有在它变化时才更新它,用到的时候只需要用get方法,这也会大幅度提高速度

在第二次作业互测时我发现的大多数问题都是格式错误,比如exp(-x)没加括号,应该是为了性能而忽略了一些小细节造成的。

心得体会

通过第一单元的学习,我知道了早点就应该注意程序的可扩展性,在写作业时不能只考虑当前的作业,要让自己的架构能够适应更多的变化,不然等到重构时会浪费很多时间。我也通过这一单元的学习,对于java更加熟悉了,要让每个类干自己该干的事情,各司其职,要思考这个方法到底应该由哪个类实现,这样架构才能清晰。总之,我的面向对象的思想又加强了。

未来方向

我认为可以将互测的代价增大一点,不然很多发现的问题只能因为代价限制而无法hack。还有就是可以在指导书里提示一些跟优化性能相关的方法,让学生更加容易上手优化。

...全文
87 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧