第一单元作业总结
第一次作业分析
度量分析
Method Metrics
Class Metrics
Module Metrics
主要思想
在第一次作业中,还未完全理解掌握面向对象的核心要义,故写出来的程序有很强烈的面向过程的特色。我规定了如下的目录结构:
├─oo_course_2021_19373345_homework_1
│ ├─homework
│ │ ├─parser
│ │ └─tools
│ └─outs
│ └─homework
│ ├─parser
│ └─tools
在./homework/parser
中我设定了三个类,分别是Pair.java
, 'Parse.java'和Term.java',分别对应一个自定义的范式、解析类和项类;在
./homework/tools中我设定了一个大类,
Tools.java',对应一个广泛的工具类。
在解决过程中,由于不需要检查格式,我首先去除多余的制表符和空格,之后去除多余的连续加减号,根据数学的定义。之后,利用'Parse.java'中的parseRawExpresssion()
方法,我们可以获得一个包含了每个已经经过解析的项,以String
的形式储存在容器中,之后对这些字符串进行进一步解析得到Term
的容器。Term
有如下属性:
private int posOrNeg; //set to -1 when neg, 1 when pos
private BigInteger coef;
private char alpha;
private BigInteger power;
然后逐个根据幂函数求导法则进行求导运算。在化简时,考虑相同幂次,然后合并同类项。
Bug分析及难点
在第一次作业中,忽略了一个较为致命的问题,即若运算结果为0,我的输出将会是一个空串。这是由与我在运算过程中把一切归零的运算都自动省略,从而导致bug的出现。
在寻找别人的bug过程中,我首先考虑特殊的输入如幂次为0或者系数为0,然后考虑连续加减号。第一次作业没有发现别人的错误。
至于难点,由于我个人以前从来没有系统地学习过面向对象的语言,在第一次作业中就明显感觉到在很多方面还是使用的面向过程思想。虽然能做,但是不优。
第二次作业分析
度量分析
Method Metrics
Class Metrics
Module Metrics
主要思想
由于第一次作业较为直观简单,而第二次作业涉及到括号的运算,解决问题的递归思路和第一次作业的按照顺序依次运算几乎完全不同,故第一次作业的框架显然不适用,必须选择重构。在重构过程中,我主要采取递归求导的方法,对每个尽量细分的项进行运算。我定义了如下几个类:ConstantTerm.java
, ContinuousMulti.java
, NormalTerm.java
, RawExpression.java
, TriTerm.java
;分别对应常数项,连乘式,普通x幂次项,包含多个项的表达式和三角函数项。其中通过递归,可以将RawExpression.java
解析成其他类中的任意一类,从而分布求解。
由于不考虑输入表达式格式的错误,我采用和作业一同样的策略即首先消除空格和制表符,进一步消除多余的加减号,之后将整个输入视为一个RawExpression
,对其分布求导。其中,对运算符号单独考虑。
如若输入为:
x+sin(x)+1+x*x*sin(x)+(1+x+sin(x))
则在求导过程中,历次递归皆针对Raw
标记进行进一步解析,解析结果如下:
##: 1*x**1 # NormalTerm
##: + # Sign
##: 1*sin(x)**1 # TriTerm
##: + # Sign
##: 1 # ConstantTerm
##: + # Sign
##: 1*x**1 # NormalTerm
##: * # Sign
##: 1*x**1 # NormalTerm
##: * # Sign
##: 1*sin(x)**1 # TriTerm
##: + # Sign
##: (1+1*x**1+1*sin(x)**1) # Raw
##: 1 # ConstantTerm
##: + # Sign
##: 1*x**1 # NormalTerm
##: + # Sign
##: 1*sin(x)**1 # TriTerm
Bug分析及难点
这个是一个较为稳妥的方法,故在强测互测中,只有一组细节性的bug,即在解析幂次和系数时,没有考虑到数据可能超出Long
范围,需直接使用BigInteger
。
在寻找别人bug时,我首先输入特殊的格式,如连续的加减号,之后对可容纳的数据范围进行考量,然后对一些特殊结果的运算进行考量,如结果为0的运算。在互测中,用这种方法发现了7个bug。
这次作业的难点即在于括号的处理和连续乘积,实际上需要两部分的递归。不过运用化整为零的思想,化繁为简,还是觉得挺简单的。
第三次作业分析
度量分析
Method Metrics
Class Metrics
Module Metrics
主要思想
可以完全沿用第二次作业的框架,只需要修改TriTerm.java
的求导方法,将Raw
引入TriTerm
括号内的求导。这一部分较为简单。
关键是表达式格式错误的判断。我采用在判断为合法输入后再进行运算,故复杂度较高。在格式判断中,我遍历整个字符串,按照题目中的要求依次判断。
Bug分析及难点
在互测中被hack的点依旧是数据范围的问题,没有考虑到数据可能超出Long
范围,需直接使用BigInteger
。原因是在对格式判断中,在解析幂次的时候被“大于50即非法”蒙蔽,没有考虑到也可能超出Long
范围,故出错。
在分析别人的程序时,由于不能针对WRONG FORMAT
进行评测,故整体hack思路和第二次一致。没有发现任何错误。
心得体会
- 第一次系统性学习面向对象语言,深刻意识到了它和面向过程语言的差异。完成每一次作业的压力大,但是在获得全AC时也颇有成就感,能够很明显感觉到编程能力的提升;
- 经过三次磕磕绊绊的迭代开发,我意识到和面向过程语言在实践上最大的区别就是必须事先用大量的精力设计一个合理的开发思路和代码模式,尽量考虑到各种迭代增量的方面。磨刀不误砍柴工,一个优秀的设计模式会给这次作业带来太多的便捷;
- 在这次作业中,些许还是怠惰了。在第二第三次作业中我没有尝试合并同类项,只是进行了最简单的排除
[*]0[*]
、1*
、**0
和**1
的情况。
© 著作权归作者所有
相关热门文章
发表评论