BUAA_OO_Unit1单元博客
目录
- 度量分析
- 度量
- 计算OO度量
- 类图
- 设计考虑
- 优点
- 缺点
- 架构设计
- hw1
- hw2
- hw3
- 架构拓展
- Bug分析
- hw1
- hw2
- hw3
- 如何发现别人的BUG
- hw1 hw2
- hw3
- 自己的优化
- 心得体会
- 未来方向
度量分析
度量
代码规模:


计算OO度量
如下


类图

设计考虑
Operate类是实现递归下降的类
而Handle则负责处理运行中遇到的各种问题
如项的分割,因子的分割等
函数的分析处理交给Function类实现
有关表达式的操作则放在Pack类里
优点
优点不多,我觉得将Factor分类处理,以及Pack子类继承可算两个
同时一些功能性方法被我封装在了Handle类中
以及函数有自己的分析类
结构还是比较清晰的
类之间也有独立性
缺点
对继承的理解还是不算深刻
子类并没有实现对父类的重写,并没有体现出子类的独特
同时对表达式和项的求导放在了Handle中,这导致了程序的耦合
应该在Pack及其子类中进行重写
架构设计
hw1
在第一次hw中,我对项的理解并不透彻
在架构中出现了并不算方便的处理
如在对单项式的处理中,我将常量和变量分开存储,即:
private HashMap<Integer, BigInteger> para;
private BigInteger myConst;
这其实忽略了常数就是x的指数为0的情况,导致写了很多不必要的冗余功能,包括getConst等
同时在实现项的加法,因子的乘法时要同时考虑const和para,显得颇为复杂
这一点在hw2中有所改进
其次,递归下降虽然在我的架构中有所体现,但个人感觉并不够
虽然我构建了Expr Term Factor三个类
Expr = Term + Term + ...
Term = Factor * Factor * ...
但是每一个类并无太大区别,都分别存储了常量和变量
这样更像是对相同的类进行了不同的取名
而且相比于其他人生成语法树的解析过程
我单纯地只是在Operate类中进行了
public Expr opeExpr(String input)
{
//...
}
public Term opeTerm(String input)
{
//...
}
public Factor opeFactor(String input)
{
//...
}
将表达式分层解析的操作
这样做导致一些功能集成在同一类中
并不够独立而在之后出现很多问题
hw2
在第二次作业中,我们新增了指数函数的表达形式
即: exp(表达式)
这一点即完全推翻了我在hw1中对多项式的存储方式
首先,myConst不再适用,因为常量包括exp(常数)
不能再单纯地使用BigInteger存储
其次,变量的存储形式para也不再适用
因为exp的指数中也可能出现变量
因此在这里对单项式做了一个统一的形式:
c1*exp(index)*x^c2
故使用Hashmap:private HashMap<BigInteger, HashMap<String, BigInteger>> para;其中用x的指数c2作为key,exp的指数index作为value中哈希表的key
由于exp指数需要转换为String类型,这里还需要写出多项式转String的方法public String packToString(Pack pack) { // TODO }同时我们新增自定义函数
最开始的想法是直接进行字符串层次的替换
即: 在读入input后,就将所有的函数进行实参的代入替换
但这样并不算方便,且与递归下降的架构并不契合
因此选择先单纯将函数作为因子
只在对因子进行处理时,对函数进行代入替换,即:public Factor opeFactor(String input) { ... else if(handle.isFunction(input)) { String str = handle.funcReplace(input); expr = this.opeExpr(str); ... } ... }这样就做到了将对函数的处理融合在递归下降的架构中
在hw1中我们将功能全部集成在了Operate类中
这并不够独立,因此在这一次作业中我进行了一次分割
新建Handle类,将所有功能性方法全部集成在此类中
而Operate类则变成单纯地对多项式地进行解析的类
hw3
本次作业新增dx求导算子
同样只需要在因子层次进行特判:
public Factor opeFactor(String input)
{
...
else if(handle.isDerive(input))
{
...
}
...
}
之后进行一次求导计算即可
而对于新增的函数可互相调用的功能
在上一次作业的递归下降就已经解决,这里不做处理亦可
架构拓展
根据现有的计算需求,可能出现的拓展有:
特殊函数,如三角函数的计算求导等
三角函数可以看作新的特殊因子,可以类似一个exp指数函数
那么就需要在para中新增三角函数的String内容
因此可能需要对单项式的存储方法进行重构
构建新的Unit类专门存储单项式的各项信息出现新定义运算
由于递归下降的优先级问题,新定义运算最好是优先级高于乘法
由此可以在Factor中再进行一次下降
根据新定义运算,拆分成Factor = Basic # Basic # ...
之后再进行处理即可
Bug分析
hw1
在第一单元我出现了两个致命bug
这导致我的强测扣了50分
T T
1.在最后对多项式的输出中,我为了实现输出的优化,在对x的系数输出中进行了一个判断
int flag = 0;
if (flag == 0)
{
if (para.get(point).equals(BigInteger.ONE))
{
System.out.print("x");
}
flag = 1;
}
else
{
if (para.get(point).equals(BigInteger.ONE))
{
System.out.print("+x");
}
}
即:如果是第一次输出,则在是正系数的情况下省略第一个正号,否则输出正号
同时若系数是1,则省略系数
但是我忽略了部分非1系数下正号的输出
2.
public void subPara(Integer point, BigInteger bigInteger)
{
BigInteger big = bigInteger;
if (para.containsKey(point))
{
big = big.subtract(para.get(point));
}
else
{
big = big.negate();
}
para.put(point, big);
}
这是我对项的减法操作,看似无问题
但注意其中的
big = big.subtract(para.get(point));
减数-被减数
由于偷懒导致的顺序错误,直接就导致了大量WA
不得不说十分愚蠢,甚至没进互测
hw2
这一次迭代也有一个十分微小的Bug
在中测时并不显露,但强测就把我斩于马下
1. 系数为0
一个很简单的数据可以形容这个问题
0
1-1
输出 0 对吧,但是事实上我的输出是
""
没错就是空串。由于在自己编纂数据时出现了大量系数为0的输出
私以为这些都是无效输出,于是在输出前进行了一步clean
大胆地清除了所有系数为0的项
很不巧,这就包含了常数0
2. Format Error
再仔细一看,怎么还有形式错误?
原来是对输出要求没有看清
由于太想优化,导致在输出时对同类项进行了合并
出现了非必要括号
改为老老实实输出后解决
3. 经典CPU_TIME_LIMIT
0
(((((((((((x^8)^8)^8)^8)^8)^8)^8)^8)^8)^8)^8)^8
一个数据爆了两个问题
- 虽然指数要求不超过8,但是可以叠乘方,导致最开始的Integer爆掉
- 过多的叠乘在算法不够优化的情况下计算太复杂
最开始对于乘方的简单解决办法是直接展开
即:
input : (x+1)^2 -> (x+1)*(x+1)
展开后再作为Term进行处理
但很显然这样的时间复杂度很高
因为需要将所有内容全部展开计算
故做一个简单的处理后调换一下计算顺序即可
input : (x+1)^2
->
str : x+1
index : 2
其中,先对str进行因子计算处理
计算完成后再进行index指数乘方
这样时间复杂度就很低了
hw3
可喜可贺,这一次终于进了互测
(再不进互测就要重修了QAQ)
强测的点很奇怪
Zero length BigInteger
用Print大法一看就发现了问题
一个简单的例子
1
f(x)=x^2
f(dx(x))
简单替换后是
dx(x)^2
但是在对求导因子的处理中并没有考虑到可能的指数符号
导致报错,修改后解决
如何发现别人的BUG
hw1 hw2
什么?原来有人互测都没进?
哭辽T A T
hw3
第一次进互测十分的激动(虽然只是C组
首先当然是先将自己曾经的BUG提交进去
然后发现同房的佬们完全不吃这套
(只有我一个人受伤的世界达成了
之后开始绞尽脑汁编数据,但总是过不了合法性检验,悲
故这提出几点可能的BUG方向:
CPU_TIME_LIMIT
对同房程序进行深度的疯狂嵌套,以期得到CPU_TIME_LIMIT的错误NULL_POINT
创造各种空式,如0*x^0,或通过计算得到空式,看是否有对此的特判处理Not Valid Factor
在因子的判断中,可能出现不属于任一因子的情况,这主要源于函数的替换
可以设计复杂的实参,看是否会让因子解析的程序报错
自己的优化
当然简单的优化还是要做的
- 系数为1的特判
1*x OR -1\*x -> x OR -x - 首个正号的省略
flag = 0 while(true) { if (flag == 0) { flag = 1; ... } else { ... } } - 系数为0项的清除
此外还有exp指数中公因式的提取public void clean() { ... for () { ... for () { ... if (bigInteger.equals(BigInteger.ZERO)) { iterator.remove(); } ... } ... } ... }
由于笨人正常写完已是心力憔悴,故三次作业中均未考虑(
心得体会
在这一整个单元的学习过程中,最让我印象深刻的就是对形式化表达的程序实现
在hw1的作业中,最开始我死板地完全依照形式化表达去处理输入的表达式
这并没有让我获得更完善的程序,而是隐藏BUG不断
在吸取了别的同学的经验后,才采取了化简输入的方法:
对连续符号进行合并,以及全部去除空白符
之后再处理就方便很多
也就是说,要对问题核心进行深度分析后,从问题导向思考解决方法
而不仅仅是题目怎么说我就怎么写
其次,程序的独立性也是需要考虑的一部分
不要将大部分功能集成在某一类中
要有对象的观念
可以归类的方法需要分门别类地实现,才能实现代码清晰,逻辑清楚
同时可扩展性和独立性也会更高
不至于牵一发而动全身
未来方向
或许可以考虑均衡一下历次作业的难度
Unit1的难度大致为
hw2 > hw1 >> hw3
这其实对很多Java不太熟悉的同学来说不算友好
或许可以考虑更加循序渐进一些
相关推荐
基于MATLAB的复合弹性模量分析,采用混合法则,结合纤维体积分数变化和图形结果。.zip
1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
基于MATLAB的自适应纯追踪曲线跟踪机器人仿真,采用多路径、自适应速度控制和图形界面可视化。.zip
1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
【数据库优化】通信行业B/O域查询性能提升:基于分区裁剪与覆盖索引的秒级溯源系统实现
内容概要:本文围绕通信行业中海量话单与信令数据的查询性能问题,系统阐述了从全表扫描到秒级响应的数据库优化路径。文章以运营商 cdr_detail 表为案例,揭示了因使用函数操作索引列(如DATE(call_start_time))和深分页(LIMIT offset, size)导致的全表扫描问题,并提出完整的优化方案:通过时间范围RANGE分区实现分区裁剪、构建msisdn与时间的联合覆盖索引、消除索引列函数运算、采用游标分页替代OFFSET等方式,使查询性能从P95 8.3秒降至290毫秒。同时介绍了执行计划分析(EXPLAIN)在调优中的关键作用,并展望了HTAP架构、向量化执行与AI自治优化器等未来方向。; 适合人群:具备一定数据库基础知识,从事通信行业数据开发、DBA或后端研发的技术人员,尤其是面对大规模时序数据查询性能瓶颈的工程师;; 使用场景及目标:①解决营业厅用户详单查询、网间结算对账、VoNR信令分析等高并发、低延迟查询场景下的性能问题;②掌握如何通过分区策略、索引设计和SQL改写实现从全表扫描到精准索引访问的优化落地; 阅读建议:建议结合实际生产环境中的大表查询案例,对照本文的反例与正例进行执行计划对比分析,并在测试环境中实践分区表创建、覆盖索引构建及游标分页改写,深入理解每项优化技巧的实际效果。
石墨提纯全球市场结构与产业发展趋势分析报告(QYResearch最新研究).docx
石墨提纯全球市场结构与产业发展趋势分析报告(QYResearch最新研究)
政府科技管理者如何提升科技成果转化政策的精准匹配与执行效率?.docx
政府科技管理者如何提升科技成果转化政策的精准匹配与执行效率?


