OO一单元多项式求导作业总结

OO一单元多项式求导作业总结

第一次作业

1. 需求分析

对简单多项式求导,分析输入格式是否符合要求,若符合要求则按同样的格式输出求导结果,否则输出WRONG FORMAT

2. 思路分析

由于这一阶段表达式相对简单,可以很方便地使用正则表达式进行匹配。通过指数、系数两个指标可以将常数项和变量项统一表示,求导法则也只与这两个指标有关。
数据结构方面,使用HashMap,将指数作为key,系数作为value,存储表达式各项,同时也方便了同类项(指数相同的项的合并)

使用IDEA的UML Support插件绘制UML图:

avatar

3. 代码度量

使用Statistic插件统计代码行数(Line of Code):

avatar

使用MetricsReloaded插件度量复杂性:

说明:

  • ev(G)基本复杂度,用来衡量程序非结构化程度
  • iv(G)模块设计复杂度,用来衡量模块判定结构
  • v(G)独立路径条数

avatar

4. bug分析

  • 关于正则表达式匹配爆栈的问题: 一开始我采用正则表达式匹配整个输入串验证其合法性,但这种方法在处理长串时会出现迭代次数过多导致爆栈的情况,因此我选择逐项匹配的方式。
  • 关于空白字符的问题: \s不仅能匹配<space>和\t,还可以匹配\f\v等目前文法规定的非法字符,因此在匹配之前有必要先进行非法字符检查

第二次作业

1. 需求变化

在第一次作业基础上,增加了以sin(x)和cos(x)为底数的幂函数项

2. 思路分析

考虑到这一次每个项仍然有固定的格式(系数*x幂函数因子*三角幂函数因子),仍然可以采用HashMap,以<x指数,sin指数,cos指数>为key,系数为value存储各项(同时进行合并同类项),对这种固定格式的项应用固定的求导法则,这样第三次作业就可以重构了

扫描二维码关注公众号,回复: 5651149 查看本文章

使用IDEA的UML Support插件绘制UML图:

avatar

3. 代码度量

使用Statistic插件统计代码行数(Line of Code):

avatar

使用MetricsReloaded插件度量复杂性:

avatar

4. bug分析

  • 一个愚蠢的bug:在填入HashMap时,由于没有重新new一个Term对象,导致后面填入的结果会覆盖前面的项,导致.equals()和.hashCode()方法不能得到正确结果

第三次作业

1. 需求变化

在第二次作业基础上,增加了在sin()和cos()内部嵌套因子的情况,增加了一对()括起来的表达式因子

2. 思路分析

由于第二次作业时的懒惰之前的方法已经不适用,需要进行重构。采用了面向求导接口的层次设计。定义了一个名为Derivation的接口,各种类型的项都实现接口中定义的方法,同时将Derivation作为统一的存储类型(常数项使用BigInteger等情况除外)。

考虑到整个表达式可以拆成由加减连接的一串项,每个项又可以拆成以乘号连接的因子,因此在顶层(表达式层)构建一个Addlist,每个元素可以是Addlist,Multilist或者其他类型的项,从而构建了树型结构。

在输入处理方面,使用了与编译器设计相似的词法分析、语法分析的方式,文法整理如下:

<Exp> = (<Term><+|->)* <Term>

<Term> = [+|-](<Factor>*)* <Factor>

<Factor> = <X>|<Number>|<SinFactor>|<CosFactor>|<PowFactor>|(<Exp>)|<Factor>

<X> = x

<Number> = [+|-](\\d)+

<SinFactor> = sin(<Factor>)

<CosFactor> = cos(<Factor>)

<PowFactor> = (<X>|<SinFactor>|<CosFactor>)^<Number>

使用IDEA的UML Support插件绘制UML图:

avatar

各个类的field和method:

avatar

3. 代码度量

使用Statistic插件统计代码行数(Line of Code):

avatar

使用MetricsReloaded插件度量复杂性:

avatar

4. bug分析

  • 关于暴力化简的问题: 采用循环遍历、逐层逐项比较的方式进行化简,发现在括号层数很多的时候运行时间很长,于是放弃了化简(本身选择的这种存储方式就不适合合并同类项以及sincos平方项合并)
  • 关于没仔细看指导书的问题: 一开始没有注意到输出结果中,sin cos括号内表达式因子需要带括号的问题,后来修改了toString方法才过了弱测第四个点

总结

三次作业的设计模式经历了纯过程式——过程式和面向对象混合——面向对象为主的过渡。由于前面没有考虑到层次化设计的需求,可扩展性差,导致后面重构过程相对繁琐。在第三次作业时尝试了Expression-Term-Factor三级继承的设计方式,但最终选择了面向接口的更为简单的实现。

猜你喜欢

转载自www.cnblogs.com/frozen-blog/p/10592549.html
今日推荐