BUAA_OO UNIT1总结

刘鸣翔-22371462 刘鸣翔-22371462 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

BUAA_OO UNIT1总结

总体框架

UML图

img

更简洁的UML图

img

框架分析

在我的设计中,项目被分成了三个部分:

第一部分为解析部分,采用了递归下降的策略,功能是对输入的表达式进行语法解析。这一部分很大程度上参考了hw_1的training,并在之后的迭代中进行了小规模重构以支持自定义函数解析。

第二部分为数据处理部分,主要是将已解析的token转化为可计算的数据,并实现了运算的方法。由于浅拷贝可能造成错误,因此这一部分的对象被设计为不可修改的,这样就在一定程度上解决了拷贝方式可能带来的问题。

第三部分主要由MainClass组成,负责输入输出和预处理。如果未来的迭代需要特殊的输入输出方式,可以为输入输出新建类。但由于三次作业中的输入输出相对简单,因此没有改变在main函数中实现输入输出的方式。

复杂度分析

方法复杂度表

MethodCogCev(G)iv(G)v(G)
Function.Function()0111
Function.Function(String)6366
Function.getAns(Poly, Poly, Poly, Parser)3144
Function.getParaNum()0111
Lexer.Lexer()0111
Lexer.Lexer(Lexer)0111
Lexer.Lexer(String)2411721
Lexer.getToken()2222
Lexer.isEmpty()0111
Lexer.next()0111
Lexer.print()1122
Lexer.processAdd(String, int)6145
Lexer.processSub(String, int)6145
MainClass.main(String[])5155
Mono.Mono()0111
Mono.Mono(BigInteger, BigInteger, Poly)0111
Mono.add(Mono)0111
Mono.detailedPrint()2233
Mono.differentiate()1212
Mono.getCoefficient()0111
Mono.getExp()0111
Mono.getIndex()0111
Mono.isCompatible(Mono)2313
Mono.isEqual(Mono)2313
Mono.mul(Mono)0111
Mono.negate()0111
Mono.print(boolean)152512
Mono.printExp(boolean)29169
Parser.Parser()0111
Parser.ParserExpression(Lexer)12111212
Parser.ParserFactor(Lexer)2381214
Parser.ParserFunction(Lexer, Function)3144
Parser.ParserTerm(Lexer)13121313
Parser.getFuncF()0111
Parser.getFuncG()0111
Parser.getFuncH()0111
Parser.getParaMap()0111
Parser.initF(String)0111
Parser.initG(String)0111
Parser.initH(String)0111
Parser.parserFactorExp(Lexer)6155
Parser.parserFactorVariable(Lexer)5144
Parser.setFuncF(Function)0111
Parser.setFuncG(Function)0111
Parser.setFuncH(Function)0111
Parser.setParserFunction(boolean)0111
Poly.Poly()0111
Poly.Poly(Mono)0111
Poly.add(Poly)0111
Poly.detailedPrint()1122
Poly.differentiate()1122
Poly.getGcd()4424
Poly.isEmpty()3324
Poly.isEqual(Poly)9646
Poly.isFactor()7548
Poly.mul(Poly)3133
Poly.negate()1122
Poly.power(BigInteger)2223
Poly.print()6456
Poly.print(BigInteger)6456
Poly.simplify()14567
Poly.sub(Poly)0111
Pre.Process(String)10199
Token.Token(TokenType, String)0111
Token.getContent()0111
Token.getType()0111
Token.getValue()3333
Token.print()0111

类复杂度表

ClassOCavgOCmaxWMC
Function3612
Lexer3.561832
MainClass555
Mono2.791139
Parser3.561464
Poly3.31753
Pre666
Token1.437
TokenTypen/an/a0

分析

一些方法的复杂度明显偏高。以Lexer.Lexer(String)方法为例,这个方法的结构大概是这样:

    Lexer(String str) {
        // ...
        while (pos < str.length()) {
            char charNow = str.charAt(pos);
            if (charNow == '+') {
                // ...
            } else if (charNow == '-') {
                // ...
            } else if (charNow == '*') {
                // ...
            } else if (charNow == '(') {
                // ...
            } else if (charNow == ')') {
                // ...
            }
            // ...
            else if (charNow == ')') {
                // ...
            }
        }
    }

实际上,其他的复杂度较高的方法,比如Parser.ParserExpression(Lexer)、Parser.ParserFactor(Lexer)、Parser.ParserFunction(Lexer, Function)、Parser.ParserTerm(Lexer),大都也有大面积的if判断。事实上,可以通过多态等更OO的方式解决这个问题。因此,在以后的作业中,我应该用更OO的方式设计程序。

迭代情况

hw_1

第一次作业的要求相对简单,但一个好的架构可以显著地降低之后迭代的工作量。因此,在第一次作业中,我一共进行了两次重构(因此有三个版本)。

第一版:采用了递归下降的思想进行解析,并使用正则表达式进行判断。但是,这一版的递归下降相对简陋,比如没有实现Lexer而是直接对字符串解析。由于解析过程写的比较随意,结果第一版的程序在解析+++1之类的数据时遇到困难。我认识到了按照构造规则进行解析的重要性(方便迭代时新规则的加入),因此有了第二版。

第二版:使用搜索的策略,严格按照构造规则解析。指导书中有规定"带符号整数内不允许包含空白字符,注意符号与整数之间也不允许包含空白字符",这让我意识到空白符也许并不是完全没有意义的(比如,+1的'+'可以解释为表达式前的符号、项前的符号、带符号的整数的符号,但是+ 1的'+'就不能解释为带符号的整数的符号)。因此,我写了搜索去寻找输入表达式的一种可能的解释。但是后来发现搜索算法的时间复杂度过高,在浏览讨论区的删空白符和消符号的优化后后,我认识到任何一个合理的解析都是正确的,并且直接解析总是可以得到一个合理的解析,于是有了第三版。

第三版:采用了较为完整的递归下降。在认真学习了training的代码后,我认识到递归下降的方法本身就有良好的可扩展性,于是在重构时,我较为完整的实现了递归下降。

hw_2

这一次作业要求加入自定义函数与exp函数。得益于递归下降,自定义函数的加入并不复杂。在自定义函数的实现方法上,由于函数表达式与最终表达式的构造规则较为接近,因而我没有采用字符串替换,而是对原有的词法解析进行扩展使其能支持表达式解析。这样可以从一定程度上避免引入新符号所带来的问题。但是由于在hw_1中我使用HashMap存储数据,为了避免HashMap嵌套带来的复杂度,我将数据部分重构为采用ArrayList表示数据。括号嵌套已经在上一次作业中实现,基本没有修改。

hw_3

这一次作业要求加入求导。其实求导可以看做一种的运算,因此直接在原有的方法上进行了扩展。函数嵌套已经在上一次作业中实现,基本没有修改。

优化分析

第一次作业中实现了基本的的输出优化(先输出正系数项,系数指数为一时省略等)。

第二次作业在第一次作业的基础上加入了简单的gcd优化(在输出exp时提取exp表达式的gcd,并选取提取gcd输出与原样输出中更短的作为输出结果)。

bug分析

在三次作业中,我都搭建了简易的评测机,但还是出现了一些bug:

  • 在hw_2中,由于输出优化导致出现了exp(-x)^2之类的错误格式。
  • 在hw_2中,由于输出优化时的疏漏导致没有特判exp(0)。
  • 在hw_3中,由于迭代时的疏忽导致在解析dx(x)*x等数据时会卡死。

这些bug反映出我测试方式的缺陷。实际上,这些bug正中我评测机的盲区。

  • 在hw_2时评测机只进行了值的比较而没有检查格式,并且没有测试极限数据。
  • 在hw_3中,由于测试样例生成具有随机性,因此有时可能会出现很长的测试样例,导致程序运行很长的时间。而在实现批量评测时,我只保留了评测结果和很少的提示信息,在遇到评测机卡死时直接重启(认为是遇到了较大的数据),结果忽略了bug导致评测机卡死这一情况。

事实上,在互测时,基于随机数据生成器发现bug的可能性比较小(毕竟同房的代码已经经过了强测的检验)。反而通过枚举一些极端的数据可能发现bug。

心得体会

良好的架构非常重要。在设计架构时应该有一定的前瞻性。比如我在hw_1的时候就实现了括号嵌套,在hw_2的时候就实现了函数嵌套,这让之后的迭代过程变得不那么复杂。相应的,由于我在hw_1的时候使用HashMap存储数据,扩展较为困难,导致在hw_2时进行了较大规模的重构。

由于上学期没有参加OOP,我在hw_1设计架构的时候采取的很多方式并不是十分OO。在hw_2与hw_3迭代时由于之前的设计具有一定的扩展性,因此对许多内容并没有做大的改变。结果是在hw_3完成后,我的程序不OO的地方有很多(比如大量的if判断,没有使用继承等OO特性)。这导致我程序的复杂度较高,也为bug的出现埋下了隐患(hw_3的bug出现在了一个复杂度较高的方法中)。在之后的作业中,我应该更多的采用OO的方式解决问题。

此外,在做测试的时候应该更加谨慎,不能迷信评测机。应该让评测机支持更全面的测试,并且采取多种不同的测试手段(比如阅读代码)。

...全文

相关推荐

这条线索还管不管?研判有效期机制避免过期线索浪费精力.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

产业园区运营负责人如何利用平台提升园区企业技术对接效率?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

电子商务概论(第七版)课程标准+课件+教案+习题答案

电子商务概论(第七版)课程标准+课件+教案+习题答案

Bryan Ding

基于格子 Boltzmann 方法的二维通道多孔介质流动模拟:理论、实现与验证(Matlab代码实现)

内容概要:本文系统阐述了基于格子Boltzmann方法(LBM)的二维通道多孔介质流动模拟的理论基础、Matlab代码实现过程及结果验证方法。详细介绍了LBM在处理复杂多孔结构流动问题中的独特优势,如对微观几何形态的高度适应性与天然并行性。采用D2Q9离散速度模型构建数值算法,通过设定合理的边界条件与碰撞算子,实现了多孔介质内流体速度场、压力场等关键物理量的动态演化模拟,并对模拟结果进行了可视化分析与物理机制解读。最终通过与理论解或已有数值结果对比,验证了所实现代码的准确性与稳定性,为相关领域的研究提供了可复现的技术路径。; 适合人群:具备流体力学基础知识和Matlab编程能力的研究生、科研人员及工程技术人员,特别适用于从事多孔介质渗流、微尺度流动建模、计算流体力学(CFD)方法研究及相关交叉学科的学者;; 使用场景及目标:①深入理解格子Boltzmann方法的核心原理及其在复杂边界流动问题中的应用技巧;②掌握利用Matlab实现LBM算法的具体流程,包括网格划分、分布函数演化、边界处理与数据后处理;③为开展多孔介质传热传质、地质渗流、生物组织血流等课题研究提供可靠的数值仿真工具与代码参考; 阅读建议:建议读者结合文中详尽的算法步骤与Matlab代码逐行研读,亲自动手运行、调试并修改程序,尝试改变多孔介质的几何构型、雷诺数等参数以观察流场变化,从而深化对LBM数值特性与物理内涵的理解,并在此基础上拓展至更复杂的实际应用场景。

冒泡芳

输电线异物数据集2739张YOLO+VOC格式.zip

数据集格式:VOC格式+YOLO格式 压缩包内含:3个文件夹,分别存储图片、xml、txt文件 JPEGImages文件夹中jpg图片总计:2739 Annotations文件夹中xml文件总计:2739 labels文件夹中txt文件总计:2739 标签种类数:4 标签名称:["balloon","kite","nest","trash"] 每个标签的框数(注意yolo格式类别顺序不和这个对应,而以labels文件夹classes.txt为准): balloon 框数 = 766 kite 框数 = 935 nest 框数 = 1480 trash 框数 = 6036 总框数:9217 图片清晰度(分辨率:像素):清晰 图片是否增强:是 标签形状:矩形框,用于目标检测识别 重要说明:暂无 特别声明:本数据集不对训练的模型或者权重文件精度作任何保证,数据集只提供准确且合理标注

不会仰游的河马君
评论
收藏 已收藏
分享
返回顶部