第一单元oo感想

一.作业思路

  三次作业整体思路大致相同,第一步处理表达式,第二步求导,第三步数据优化,第四步输出数据  

  前两次作业

  第一次作业较为简单,只需要考虑常数因子以及幂函数因子即可,对于每一个项构造一个对象,对象中两个成员变量分别是幂函数系数和幂函数指数,最后进行求导即可。

  第二次作业多了简单正余弦函数,对于每一个项构造对象,每一个都可以化简为常数*幂函数*正弦函数*余弦函数,对象成员变量四个,分别是系数,幂函数指数,正弦函数指数,余弦函数指数,最后利用乘法规则求导即可。第二次化简表达式主要依据

  sin(x)^2+cos(x)^2=1公式化简,通过一层循环,只要满足x指数相等,正余弦函数指数互相差2,或者单独一个指数差2,系数不需要相等,根据对应情况化简即可。

       对于前两次作业判断正误时,均可以根据表达式规律构造大正则直接匹配,然后每项单独进行提取构造对象。唯一存在的问题就是使用正则表达式可能出现爆栈问题,此时将正则表达式匹配模式由贪心模式变为独占模式即可,因为使用规律匹配不需要回溯。

  第三次作业

  第三次作业难度相比于前两次大大增加,也需要真正使用到面向对象的相关知识继承和接口。通过接口可以将不同的对象放到同一个接口数组中,施行相同的操作。构建常数因子对象,幂函数因子对象,正余弦函数因子对象,以及嵌套因子和表达式因子对象。   

   1.处理表达式

  我没有采取助教推荐的构建表达式树,我运用到了栈和表达式求值的思想。构造符号栈和表达式栈,首先遍历:读到左括号循环匹配到右括号,将整体创建嵌套因子对象,读到s\c判断是否嵌套构造三角函数对象或嵌套因子对象,常数构造常数因子对象,x构造幂函数因子对象。读到+,-,扔进符号栈

   样例:sin(x)*x*(cos(x)+x)+2

       分别构造sin(x),x,(cos(x)+x)进入对象栈,符号栈* * +,读到+就要出栈,读到n个*,对象栈就出n+1个对象,分别求导即可,对于嵌套和表达式因子的求导使用递归,最后输出结果即可。

   2.判断表达式正误

  除了用递归下降来判断表达式的正误,还有一个方法。首先明确,表达式由项加减构成,项由因子通过乘法相连,与第二次相比多了一个嵌套因子和表达式因子,表达式由因子构成,而因子又可以通过表达式两端套括号构成,嵌套因子又可以由表达式因子构成,所以这就好比是一个你中有我我中有你的问题,我的解决方法就是使用一个循环进行替换,首先空格特判;然后判断幂不超过10000;将常数因子、幂函数因子、三角函数因子归为简单因子,将形如 (简单因子构成的表达式) 变为x,但是这样有个问题,sin(x)本来正确这样会替换成错误,所以还要把形如 sin(简单因子)、cos(简单因子) 也替换成x,而且优先级高于括号套表达式,这样循环往复第三次作业的表达式就会变为第二次作业的表达式,再用第二次的方法判断正确性即可,但是每次替换之前需要判断是否出现 (表达式) 后跟着幂指数,如果有停止替换输出WF即可。

  样例:sin((x+cos((sin((x^2-cos(x)^3+sin(x)^4))+cos((sin(x)-x))))))

  第一次替换(x^2-cos(x)^3+sin(x)^4)、(sin(x)-x)变为x,结果sin((x+cos((sin(x)+cos(x)))));

  第二次替换(sin(x)+cos(x))为x,结果sin((x+cos(x)));

       第三次替换(x+cos(x))为x,结果sin(x);

  第四次替换sin(x)为x,结果为x,符合第二次表达式,不需要输出WF,接着求导即可。

    缺点  

  这样的做法过于面向过程,而且功能不宜扩展。

    类图 

                              

 

  度量分析


 

二.BUG产生与修复

  1.个人BUG问题

  I.空格特判没有考虑全所有情况

  II.正则表达式少写了转义符\或者少了+

  这两个BUG只有通过构造大量的测试样例才可以发现。

  III.第三次强测结果出现了两个TIE

  原因:在一个判断语句条件中调用递归的结果,后期再次使用递归相当一次递归时就使用了两次递归,修改时直接将递归的结果放在一个中间变量,后期直接使用该变量就不再出现TIE了,通过这种问题可以积累经验。

  2.互测他人BUG问题

  I.在自己编写代码时一定会出一些复杂数据不易处理的情况,这些数据在互测时比较有用。

  II.读他人代码,主要以输入处理和正则表达式为主,这些地方比较容易出现问题。

  III.数据化简时候BUG也比较多,需要深入分析他人代码,盲狙效率很低。


 

三.个人感想

  1.作业完成过程

  对于每一次作业,一定要提前构思好结构,而不是直接写代码,好的结构可以大大简化后期的工作。当进行代码的编写时,不用提前考虑好所有代码的细节,由于面向对象的特性,我们可以先写一些简单的类,在类中写好对应的方法,后期直接引用提前写好的对象,最后把最难的部分完成即可。

  2.性能优化问题

  性能是评测一个程序好坏的一大方面,这三次作业评判程序性能以输出结构的长度作为依据。前两次优化相对简单,但最后一次并不简单,这就是一个博弈的过程,一味地追求性能,很容易带来一些额外的BUG,最后得不偿失。在我看来,既然想要得到高性能分,一定也要做好优化失败最后成绩很低的心里准备。

posted on 2019-03-26 20:19  continho  阅读(125)  评论(0编辑  收藏  举报