目录
一.程序结构分析
一.第一次作业
基于度类
类名 | 属性个数 | 方法个数 | 总代码规模 |
---|---|---|---|
MainClass | 0 | 2 | 47 |
Preprocess | 1 | 2 | 34 |
Lexer | 3 | 5 | 39 |
Parser | 1 | 7 | 139 |
Term | 1 | 6 | 38 |
Expr | 1 | 6 | 69 |
Exprpower | 2 | 3 | 16 |
Number | 1 | 4 | 17 |
Power | 1 | 3 | 14 |
类的复杂度
二.第二次作业
基于度类
类的复杂度
三.第三次作业
基于度类
类的复杂度
类图 (以第三次作业为例)
二.架构设计体验
第一次架构
第一次架构时,就考虑到后面两次的迭代,所以后面没有进行任何重构,后面实际添加的代码量也很少,主要的时间都花在具体的实现上和debug上,第一次的架构主要还是按照课程组的要求和提供的代码进行设计,选择递归下降的方式进行处理,对输入的表达式进行解析和分类,设计不同的类来储存不同的factor,term和expression。对于最后结果的存储,最开始选用的HashMap进行储存的,对于最终结果的每一项,都只会有指数和系数,key值存指数,便于合并同类项,value值存系数。
第二次架构
第二次架构相比于第一次的架构,最大的改动就是将结果从HashMap存储改为Mono,Poly类进行存储。
因为对于第二次作业,需要对指数上的表达式进行储存到最后的结果,所以设计了一个Mono类和Poly类来进行管理,总体也就是替换掉之前的HashMap,所以当时写的时候也很简单。具体第二次作业的完成因为第一次架构的比较合理,最终具体的实现也就加了十几行代码,主要的难题还是解决当时的bug。对于第二次表达式的预处理,我新建了一个类来解决函数的替换,这样的预处理我个人感觉比在parser里进行解析简单的多,第三次作业也不需要任何更改,还有就是debug也很简单,只需要输出替换后的结果来检查最后的结果的正确性。
第二次最大的工程量还是表达式的化简,当时对于不同最小因子的合并,要比较指数上的表达式是否相等才可以进行合并,所以最大的难点就是判断两个Poly是否相等。我采用的方法还是递归比较,直到最终表达式中的因子上的指数上为空时为最终递归的终点,再向上一级比较指数和系数是否相等,最终判断两个表达式是否相等。
第三次架构
第三次架构添加的内容和第二次添加的内容基本上是差不多,主要难点在于表达式的求导,最后的解决方式还是递归解决,对表达式的每个因子求导,因子中的指数有可能为一个表达式,继续递归,直到指数为空,得出求导后的结果,返回到上一级,直到求出整个表达式的求导结果。
三.程序的bug
在三次作业的强测和互测中,在第一次的强测中出现了输出格式的错误,当时写输出时,为了图方便,将结果的1*直接删除,可是在遇到121*x是会直接变成12x,导致最终的结果会报format error的问题,第一次的强测和互测都是因为这个原因,修复bug也是多加了一个判断来解决这个小bug的。第二次的强测出现了TLE的bug,主要原因还是代码的重复计算,修改方式大概就是将指数单独存起来,而不是像之前的将所有的指数下的表达式都存在terms中,这样的弊端在于(x+1)^8,会将(x+1)都解析一遍,当多层嵌套时,会导致复杂度会非常的高,改后的代码不会重复计算,当解析好(x+1)时,会直接将8个(x+1)相乘,不会再次解析剩余的7个(x+1),这样的话会省去很多重复的代码运行。第三次的强测和互测都没有出现任何的bug,但在互测的房间出现了多层exp嵌套的情况,也是刀了房间里的四个人,这种情况对我自己的代码处理起来没有什么难度,只是需要对每一层解析一下就可以解决的,基本上是没有太多的循环嵌套的。
自己发现别人程序bug所采用的策略
主要就是临界值的hack和多层嵌套的hack,但是互测的cost限制了多层嵌套的hack,当时也是没有想到exp的多层嵌套,所以也没有hack到这个点。临界值的hack,大家都处理的很好,也是没有成功hack到。
四.自己进行的优化
自己的优化主要分为两个部分:递归层面优化和性能的优化。
递归层面的优化主要在自己写代码时,为了代码的可实现性和美观性,递归是最好的选择,用最少的代码量来实现多层嵌套的比较和求导。
性能层面的优化还是之前提到的对于指数的处理,指数的表达式只解析一次,不会重复相同的解析多次,使程序的性能得到优化。
五.心得体会
通过第一单元oo的迭代,让我对递归下降的算法有了非常清楚的认识。在这一单元的迭代中,第一次作业的工作量是最大的,要考虑到以后两次的迭代,所以参考了大量的资料,之前也没有了解过递归下降的算法,所以写的十分煎熬。至于二三次的迭代,并没有花太多时间在代码的架构上,主要就是写完之后的debug和代码性能的优化上,写的也没有第一次那么煎熬。总的来说,第一单元的迭代作业让我学习到了很多新的东西。
六.未来方向
我觉得第一单元的性能优化方面没有明确的方向,递归下降给了练习代码,我觉得关于性能方面也可以明确优化方向。还有在单元结束后可以发布一些好的架构。后面单元的参考资料也希望可以更加的详细。