OO 第一单元总结 表达式求导
OO第一单元通过三次递进式的作业让我们实现表达式求导,在这几次作业中我也有很多收获。下面就回顾一下前三次作业中存在的问题。
在个人看来,表达式求导的难点主要有三部分——对输入的处理、表达式的存储结构以及化简。这三次作业我所采用的表达式存储结构都不相同,不过重构的速度还是比较快的(安慰自己)。
第一次作业
在第一次作业中,我的程序总体架构为提取幂函数为Poly对象,建立Polynomial类解析表达式创建幂函数对象,在主类Derivative中进行部分性能优化工作。
① 程序结构分析
UML类图:
第一次作业的幂函数因子较为简单,代码中仅提炼出Poly对象,并在其内部实现求导方法。
Method复杂度:
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
Derivative.main(String[]) | 1 | 1 | 1 |
Derivative.printAnswer(HashMap<BigInteger, Poly>) | 4 | 5 | 7 |
Poly.Poly(BigInteger,BigInteger) | 1 | 1 | 1 |
Poly.addCoef(BigInteger) | 1 | 1 | 1 |
Poly.compareTo(Object) | 1 | 1 | 1 |
Poly.derivative() | 1 | 2 | 2 |
Poly.equals(Object) | 2 | 2 | 2 |
Poly.getCoeff() | 1 | 1 | 1 |
Poly.getIndex() | 1 | 1 | 1 |
Poly.hashCode() | 1 | 1 | 1 |
Poly.toString() | 1 | 11 | 12 |
Polynomial.Polynomial(String) | 1 | 1 | 1 |
Polynomial.getPolyitem() | 1 | 2 | 2 |
Polynomial.getfirstitem() | 1 | 9 | 10 |
第一次作业中, 化简主要在主类Derivative的printAnswer()方法(将第一个正项优先输出)和Poly类的toString()方法中,printAnswer()涉及对表达式的遍历,基本复杂性高;toString()则包含大量条件语句,多次调用了BigInteger中的方法,循环依赖性高。而表达式解析我采用的是正则+状态机的策略(这个策略三次作业均沿用,感觉还是很舒服的),在getfirstitem()中处理不同类型输入并归一化,代码较为复杂。
② 程序Bug分析
第一次作业在强测、互测中均未出现Bug。
③ 互测采用策略
互测时我采用的策略是“补刀”。我先是用简单的自动测试程序跑了下房间内成员的代码,不过貌似没有出现问题;然而圣杯战争发生了转机——Rider竟然拿下了一血!
于是我一一检查其他成员的代码,发现Berserker的正则存在问题:在正则中匹配的是“[+|-]{0,2}(\\d*.)?x(..[+|-]?\\d+)?
”,其中的“.”可匹配任意字符,就会错误解析表达式。
第一次互测时认真读了屋内其他同学的代码,感觉还是很有收获的。之后两次大部分都读不下去,可读性实在是让人肝疼……放到评测姬里自生自灭吧!另外这次互测也让我意识到了高工同学的可怕之处(误),全屋子就这一个Bug,大佬换着花样hack……卷卷更健康。