BUAA OO UNIT1 多项式求导单元总结
UNIT 1 多项式求导
Homework 1
-
score:100
-
代码增量
-
本次作业较为简单,只需建立形如\(ax^p\)的单项式类和形如\(\sum a_ix_x^{p_1}\)的多项式类即可
- 多项式类使用TreeMap实现,value为单项式,key为单项式的指数
- 使用merge更新多项式,重写toString即可
-
读入部分只需编写正则表达式读取每一项,再用第二层正则表达式读取项中的x、常数、指数即可
- 读入x,则指数+1
- 读入**p,则指数+p-1
-
输出部分将正项、负项分别转成String,然后将正项拼在负项之前,去除开头的+号
-
-
Bug&Fix
- Bug: None
- Fix: Pass
-
metrics
Method | ev(G) | Rank | Line | Rank |
---|---|---|---|---|
wk.Re.ngrp() | 1.0 | 2 | 28 | 1 |
wk.Atom.str() | 5.0 | 1 | 17 | 2 |
wk.Main.main(String[]) | 1.0 | 2 | 9 | 3 |
wk.Poly.toString() | 1.0 | 2 | 8 | 4 |
wk.Poly.df() | 1.0 | 2 | 7 | 5 |
wk.Atom.df() | 1.0 | 2 | 5 | 6 |
wk.Atom.equals(Atom) | 1.0 | 2 | 3 | 10 |
- 类图
Homework 2
-
score: 84.59
-
代码增量
- 递归下降读入表达式
- 虽然用栈也能实现同样的功能,但为了可扩展性还是选择了递归下降法
- 但实际上递归下降在java上并不易于实现,递归下降法最终也没有达到预期的可扩展性
- 多态类存储表达式
- 建立抽象类Fun,实现Comparable、Cloneable接口,声明必须包含的求导、化简、修改等方法
- 各函数的具体类继承Fun,其中,常量、sin、cos、x的实现较为简单
- 注意到系数和指数分别可看成累加和连乘的简写形式,所以只需定义累加和连乘类,使用map存储每一个元素,key为元素,value为系数或指数
- 由于涉及递归,我不太信任hashcode的安全性,因此使用treemap实现,compareTo方法为递归比较。
- 递归下降读入表达式
-
性能优化
- 删除0系数、0指数成分
- sum、prod类自带合并同类项
- 不支持因式分解
-
Bug&Fix
- Bug: 由于其他课程压力过大,加上因为重构耗费了两倍的时间,没有时间仔细测试本次作业,导致出现丢失符号的bug,被hack19次。
- Fix:关闭导致此问题的性能优化代码,将return null改为return 0多项式。
-
metrics
BUG方法 | 圈复杂度 | rank | 代码长度 | rank |
---|---|---|---|---|
Prod.trim() | 6.0 | 1 | 25 | 2 |
Sum.trim() | 4.0 | 3 | 1 | 5 |
Main.main() | 3.0 | 8 | 17 | 5 |
其他方法 | ev(G) | Rank | Line | Rank |
---|---|---|---|---|
Sum.toString() | 3.0 | 8 | 27 | 1 |
Prod.compareTo(Fun) | 5.0 | 2 | 22 | 3 |
Sum.compareTo(Fun) | 5.0 | 2 | 22 | 4 |
Prod.push(Fun,BigInteger) | 3.0 | 8 | 16 | 7 |
Sum.push(Fun,BigInteger) | 3.0 | 8 | 15 | 8 |
Re.exp() | 4.0 | 4 | 14 | 11 |
- 类图
Homework 3
-
score:99.56
-
代码增量
-
sin、cos函数嵌套
- sin、cos内部增加child属性记录括号中的因子,略微修改即可
-
WRONG FORMAT
- 增加Err函数,化简和求导均返回自身,toString方法返回“WRONG FORMAT!”
- 由于多正负号、过大的指数、sin、cos内部嵌套多项式等多种情况不合法,故原先的递归下降代码需重写
-
性能优化
- 总体上仍然是很多低垂的果实没有拾取,考虑到时间分配以及最终成绩,这看来是明智之举
- 支持脱壳:累加类、连乘类中若仅有一个元素,则返回该元素,删除原类
- 不支持因式分解
-
-
Bug&Fix
- Bug: None
- Fix: Pass
-
Method Metrics
-
Class Metrics
-
Code Lines
-
Method Lines
-
chart
- 类图
互测与hack
- 没有自动评测机,互测就无从谈起
- 第一次作业由于自动评测机没搭好,也不想在这上面花太多时间,所以就随便测了测自动编译能不能用,意外hack了一个人。
- 乱搞压标算
- 其实大家的整体结构相差并不大,存在结构性问题的几率较小,更多是因为嵌套和控制分支太多造成隐藏bug,因此随机测试效果会比较好。
- 第二次作业我的数据基本上为手工构造,基本思路是先构造连续规则的数据,然后向其中乱搞地加入一些符号。然后16次提交成功hack24次,当然有我在B屋的原因。
- 第三次作业我把这种乱搞过程自动化,就形成了我的数据生成器,9次提交成功14次。
- 空白字符很重要
- 强测不含空白字符导致一部分实现得并不好的同学也来到了A屋,我屋里有三份代码本地测试时通过率不足50%,我甚至不得不替三位同学修复bug才能使评测继续进行。
- 这个过程中,我发现他们实现递归下降的方式极为复杂,存在多重嵌套调用和多重控制流,这些代码中或是出现笔误,或是有情况未考虑,使得他们把正确输入错判为WF
- 丢失字符
- 后续还发现有位同学在第三次作业出现了我第二次作业中的错误——丢失字符,推测可能是第三次作业新加入了优化代码,没有充分测试导致。
总结
-
Java编程技巧
- 三元表达式真香
- 函数式编程真香
- 正则表达式及其难用
-
自动评测机
-
别人的轮子就是最好的轮子
自动编译部分使用Github WinGrep项目搜索源文件和package。实际运行时发现bug,上午反馈给开发者,晚上就收到修复。
-
命令行也有好ui
实时进度条、评测结果统计表等等特性并不难实现,却能显著提高评测机可用性
-
乱搞压标算——论好的数据生成器
第三次作业中我的数据生成方案是
- 给每种符号编号
- 生成只含x和常数对应编号的序列
- 向其中随机洒入括号、sin、cos函数,注意括号匹配
- 输出时随机加空白符
这个生成器成功找到了我和几位朋友平均每人5个bug,且速度极快O(n),与输出同复杂度
-
-
时间管理
- 重构代码是灾难