北航OO第一单元总结:表达式的解析-程序员宅基地

技术标签: java  intellij-idea  

第一单元总结:表达式的解析

第一单元的三次迭代终于完成,在三周时间的代码训练中,我初步掌握了表达式解析的有关方法,对解析时所常用的架构有了更深的了解,

本单元作业中具体如下:

目标简介

作业一:通过正则表达式或递归下降方式,识别表达式、项、因子,因子包括常数、幂函数、表达式,因而进一步去除括号。

作业二:同样去除表达式括号,但是输入正式的表达式前先读入n个自定义函数(fgh),并且引入exp指数函数,指数函数类似幂函数的结构,也可带指数。

作业三:支持求导操作,新增求导算子,同时作业函数表达式中支持调用其他“已定义的”函数.

个人具体构建过程

分析维度

用MetricReloaded分析方法和类复杂度时,几个维度含义如下

CogC :关于理解方面

着重从阅读的角度来看,将一段代码复杂程度估算成一个具体数字,多次的重复遍历和嵌套将提升复杂度。

ev(G) :关于结构方面

是基本复杂度,来衡量程序非结构化程度,非结构成分降低了程序的质量,增加了代码的维护难度,同时也导致debug难度上升

iv(G):关于模块方面

是模块设计复杂度,来衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。模块设计复杂度是从模块流程图中移去那些不包含调用子模块的判定和循环结构后得出的圈复杂度,所以一般小于圈复杂度

v(G) : 关于测试方面

用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,经验表明,程序的可能错误和高的圈复杂度有着很大关系。

类的复杂度:

OCavg :平均操作复杂度

OCmax:最大操作复杂度

WMC : 加权方法复杂度

第一次作业

主要思路
储存数据类

第一作业框架的构建十分困难,关键是从何入手。再纠结不知多久之后,根据题目引导的架构

在这里插入图片描述

本人首先先建立表达式、项、因子三个类,将因子类设为虚类,并使表达式类继续继承因子类。这样就构建好了具体实现的存储类,每个对象中存放对应的数据。

解析类

之后就要考虑这些类实现的方法。首先应当选用递归下降进行解析,因为根据本人理解来看,递归下降更为灵活(虽然本次不要求括号嵌套,但是在后续迭代中,如果继续使用正则表达式匹配将非常棘手)

递归下降时,解析表达式就是向表达式类中添加各个项的过程,而解析项就是向项类中添加各个因子的过程。表达式的建立是一个动态的过程,每添加一个项就产生一个静态的表达式。

括号化简方法

化简应当伴于添加左右,即一边添加因子或项一边化简。

在表达式中添加项之时,可分两种情况讨论

  • 添加的是无表达式项,则直接添加,同类项则合并
  • 添加的是有表达式的项,则先将项中的每个表达式相乘,得到的表达式再与项中其他的因子相乘展开,得到一个项的hashset,再将每个项依次加入,同类项则合并

在项中添加因子就较简单了,若为数字则系数相乘,若为幂函数则与已有幂函数指数相加

细节问题

主要的细节问题出现在提高性能分方面,总结来说有以下几点

表达式中

  • 首项若是正项则不显示加号
  • 项若是0则不显示

项中

  • 系数为1则不显示
  • 系数为-1则直接加负号

另外还有同学说如果有正项优先把正项放第一个,有时能省一个正号

bug分析

第一次作业遇到的bug不多,且多为疏忽笔误导致,最后强测没有出问题。

印象最深的错误是添加项或因子时把原来的对象加进去了,要注意深拷贝一个对象再加入,否则会出现各种奇奇怪怪的错误()

hack方面

本次作业hack并未成功,在尝试hack中会尽量考虑边界值的特殊情况,例如00,x8等

类图

由如上说明构成类图

数据存储类:

在这里插入图片描述

解析类和预处理类:
在这里插入图片描述

复杂度

在这里插入图片描述
在这里插入图片描述

可以看到add相关即添加因子或项以及化简相关方法较为复杂,这几个方法具有很多多层嵌套循环,在处理中不断相互递归调用,因而复杂度比较高
在这里插入图片描述
可以看到parse和Term中复杂度较高,主要因为parse是解析类,因而集成了递归下降算法的核心。Term中作为将Factor与Expr相连接的类,本人将很多处理及化简Term中因子的方法加到了Term中,又分了很多种情况讨论处理,最后导致Term类较为臃肿,可以考虑将化简等方法单独拎出构成新的类,降低复杂度

第二次作业

主要思路
存储数据类
  • 对于自定义函数,新增Definefunc类,存储每个自定义函数的名字、函数体、变量,其中变量和函数体都用String类存储,便于之后调用实参处理
  • 对于指数函数,新增Pow类,专门存储指数函数因子。其中变量用Factor存储,在存入时首先为Expr,之后再判断是否能化简,转化为数字或幂函数,这样可以省一个括号。
解析类

大体框架改的不多,主要新增对函数因子和指数因子的判断

函数调用方法

首先将形参对应转化为“a-c“,以为了防止之后替换实参时错误替换,再将”a-c"转化为实参,注意在两边加括号,其中exp符号单独转化,防止x也被替换

细节问题
指数函数的优化

个人认为这是本次作业最能体现代码层次结构清晰度的地方,我的优化方案总体如下

term中加指数函数时:

  • 如果碰到原本已有相同指数的指数函数,则将内部变量相加合并
  • 如果碰到原本已有相同变量的指数函数,则将指数相加合并

Expr中加term时:

  • 新增equal函数以便于判断是否是同类项,equal函数时Factor的重写方法,可以递归判断两个Term中的Exp、Pow是否相等,如果都相等则判断为同类项,可以系数相加合并

还有个人没有实现的部分,判断exp内部是否有共同Number因子,可以提出来放到指数上,当数字很大时可以省很多空间。

bug分析

强测惨不忍睹,最后改完发现有多达四个地方有问题。

  1. toString方法的重写,导致程序在运行和调试时出现不一样的情况。
  2. 在exp解析内部变量时,采用的是parseFactor,这样导致之后转化为字符串化简时如果为带幂次的Expr,则幂次打印不出来,应该保险改为parseExpr。
  3. 判断两个项是否为同类项时,只判断了第一个项中的Exp和Pow在第二个项中有就直接判为相等,导致合并同类项错误,应该遵循相等的如下原则:第一个有的第二个有,第二个有的第一个也有。
  4. 还是对象克隆的问题,在添加新的exp时,应当新建一个对象

原因感觉还是粗心导致,另外应当充分利用java的clone类,否则自己每次手动构造一个新的类难免会忘记或者出问题

类图

由如上说明生成类图

数据存储类:
在这里插入图片描述

解析类和预处理类:
在这里插入图片描述

而由预处理得到自定义函数类的一个Hashset,,funcset:

在这里插入图片描述

复杂度

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
除了第一次作业化简相关方法复杂度较高以外,对函数因子传递的parseFuncFactor方法也较为复杂,因为需要分别处理读入实参等数据,处理起来比较冗长。

此外用于equal方法如上述所说是为了判断是否为同类项,递归的调用导致系统有额外的开销,属于是牺牲性能换性能分()。
在这里插入图片描述

依旧是熟悉的parse、Term,此外由于判断同类项的出现,Expr中每出现一个新Term就需要嵌套循环每个Term及其每个因子,实现起来比较复杂。

第三次作业

主要思路

这次作业要添加的不算多,只要新增一个Derivator类,用于返回一个表达式求导的结果即可。

求导方法

从底层开始

  • 对Factor求导这里不会出现Expr的Factor,所以直接套用公式就行
  • 对Term求导时,遍历Factor,对其中一个求导再乘上其他Factor构成一个新的Term,最终返回的应该是一个Expr
  • 对Expr求导时,遍历Term,将每个Term求导的结果合并得到一个新的Expr

如此一来通过遍历可较为清晰展现

bug分析

竟然是之前遗留下来的bug,对自定义函数的每个实参进行解析时,用的是parseFactor,和第二次作业exp内部解析bug是同个问题,应当改为parseExpr(),而且之前的强测也没测出来。

原因还是自己数据构造不够充分,甚至没有考虑到实参中有带幂次的表达式因子的情况。
在这里插入图片描述

hack方面

因为这次作业不同于以往的只是求导和函数定义时的调用,因此测试时多考虑有三个函数的调用定义情况

而由于求导因子存在的位置比较多,可以尝试在函数实参内、exp变量内出现,并且求导的表达式可以涵盖多个表达式因子、幂函数、指数函数混合的情况。

类图

在这里插入图片描述

数据存储类相同,解析类中只多加一个Derivator,具体在上文已说明:
在这里插入图片描述

复杂度

在这里插入图片描述
在这里插入图片描述

因为其他类与方法与第二次作业基本无区别,在这里只给出Derivator相关复杂度。

由于其本身又是以嵌套调用为基本方法的类,因而每个方法并不复杂,但是对于求导时调用的整个类的方法来说依然较为复杂。

心得体会

这个单元的三次作业做得很艰难,遇到的bug也很多,但正是因为这样的困难也让我对面向对象编程的思维方式逐渐熟练起来,主要体会有以下几点:

  1. 一个好的架构永远是第一位的。在第一周时碰到全新的需求和问题时完全就是一脸茫然,刚开始的设计是最难的,也必须要为之后两次作业的扩展做好铺垫。而未经思考的下手往往会导致之后不必要的重构,因此为了设计的可扩展性,必须先有对整体的思考,然后再在构造时不断优化,如此才能提高效率。

  2. 写完代码后要充分进行测试,可以搭建评测机加快测试。例如个人第二次的bug中,关于合并同类项时判断错误的问题,如果能测试到位完全不用到了强测之后才得以被发现。

  3. 要充分利用讨论区,有好的思路应该分享,并及时发现讨论区中优秀的想法或者架构,必要时可以参考而进行重构

到全新的需求和问题时完全就是一脸茫然,刚开始的设计是最难的,也必须要为之后两次作业的扩展做好铺垫。而未经思考的下手往往会导致之后不必要的重构,因此为了设计的可扩展性,必须先有对整体的思考,然后再在构造时不断优化,如此才能提高效率。

  1. 写完代码后要充分进行测试,可以搭建评测机加快测试。例如个人第二次的bug中,关于合并同类项时判断错误的问题,如果能测试到位完全不用到了强测之后才得以被发现。

  2. 要充分利用讨论区,有好的思路应该分享,并及时发现讨论区中优秀的想法或者架构,必要时可以参考而进行重构

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Jinhua1121/article/details/136875007

智能推荐

Python pandas练习Retuns50stocks股票,纯英文ipynb作业20题,100%正确答案_create a function that takes a positive integer an-程序员宅基地

文章浏览阅读848次,点赞2次,收藏3次。#%% mdAssigment 4Instructions: This problem set should be done individuallyAnswer each question in the designated space belowAfter you are done. save and upload in blackboard.Please check that you are submitting the correct file. One way to avoid mist_create a function that takes a positive integer and returns the next bigger

FDR校正的程序实现及严格程度对比_fdr校正后全没有意义-程序员宅基地

文章浏览阅读2.4w次,点赞9次,收藏44次。FDR校正的程序实现及严格程度对比前言 做统计分析就离不开P value<0.05,而写过科研文章的人也都知道没有经过FDR校正的P值就像一盘散沙,不用风吹,走两步自个儿就散了。那么FDR校正这个让人又爱又恨的东西是什么呢?又是如何实现呢? 原理是这样:设总共有m个候选基因,每个基因对应的p值从小到大排列分别是 p(1),p(2),..._fdr校正后全没有意义

淦VINS-MONO源码 01--IMU的误差模型和标定-程序员宅基地

文章浏览阅读921次。IMU的误差模型和标定工作原理加速度计工作原理陀螺仪测量原理误差来源IMU噪声模型biasscale轴偏差IMU校准确定性误差六面法标定bias和scale factor温度相关的参数标定随机误差高斯白噪声Bias 随机游走艾伦方差标定数学模型加速度计数学模型陀螺仪数学模型在看完orb-slam后,也投了一些实习,发现纯视觉的方案在很多方面都没得到采用,特别是自动驾驶中定位感知方面,基本上是雷达+IMU+相机+GPS等等的多传感器融合,所以接下来的计划会看看vins-mono和loam的源代码,一个是IM

Dotween常用方法详解-程序员宅基地

文章浏览阅读10w+次,点赞213次,收藏880次。Dotween是unity里非常常用的插件,但是很多人应该没有仔细的阅读过它的api,它实际有很多好用的方法,下面我就针对一些相对常用的方法,做下总结:一、Unity常用组件拓展方法(1) Transform拓展方法1)Position 改变世界坐标 移动方法,第一个参数是要移动到的目标点,不是移动这个向量的距离 transform.DOMov..._dotween

matlab图片纹理特征直方图,常用的图像特征有颜色特征、纹理特征、形状特征、空间关系特征。...-程序员宅基地

文章浏览阅读1k次。常用的图像特征有颜色特征、纹理特征、形状特征、空间关系特征。一 颜色特征(一)特点:颜色特征是一种全局特征,描述了图像或图像区域所对应的景物的表面性质。一般颜色特征是基于像素点的特征,此时所有属于图像或图像区域的像素都有各自的贡献。由于颜色对图像或图像区域的方向、大小等变化不敏感,所以颜色特征不能很好地捕捉图像中对象的局部特征。另外,仅使用颜色特征查询时,如果数据库很大,常会将许多不需要的图像也检...

OutSystems中,利用分组数据来计算值_outsystems tan関数-程序员宅基地

文章浏览阅读418次。将数据放入组中以计算聚合值,从而提取更多信息。在 OutSystems 中,您可以使用聚合函数对相同数据组计算值。利用聚合方式获取数据和执行以下操作:在具有相同数据的属性中,菜单中选择 Group by &amp;lt;attribute&amp;gt;;在要计算的属性中,使用菜单并选择聚合函数,例如 Count;在属性上对聚合函数进行分组或使用后,这些属性将成为聚合的唯一输出。示例在 GoOutW..._outsystems tan関数

随便推点

4.链表组件(LeetCode 817)_给定链表头结点 head,该链表上的每个结点都有一个唯一的整型值 。 同时给定列表 g-程序员宅基地

文章浏览阅读254次。问题描述 :给定链表头结点 head,该链表上的每个结点都有一个唯一的整型值 。同时给定列表 G,该列表是上述链表中整型值的一个子集。返回列表 G 中组件的个数,这里对组件的定义为:链表中一段极长连续结点的值(该值必须在列表 G 中)构成的集合。极长的含义是:这段连续结点的前面或后面结点不属于G。示例 1:输入:head: 0->1->2->3G = [0, 1, 3]输出: 2解释:链表中,0 和 1 是相连接的,且 G 中不包含 2,所以 [0, 1] 是 G 的一_给定链表头结点 head,该链表上的每个结点都有一个唯一的整型值 。 同时给定列表 g

使用神器MobaXterm连接远程mysql和redis-程序员宅基地

文章浏览阅读3.4k次。https://mobaxterm.mobatek.net/download-home-edition.htmlmysqlredis连接测试mysql127.0.0.13307密码使用线上密码redis127.0.0.16380密码使用线上密码转载于:https://www.cnblogs.com/cxscode/...

Shell判断字符串是否为空-程序员宅基地

文章浏览阅读1k次。主要有以下几种方法:echo “$str”|awk '{print length($0)}'expr length “$str”echo “$str”|wc -c但是第三种得出的值会多1,可能是把结束符也计算在内了判断字符串为空的方法有三种:if [ "$str" ="" ] if [ x"$str" = x ]if [ -z "$str" ] (-n ...

ingress-nginx-限速_ingress nginx速率限制-程序员宅基地

文章浏览阅读2.8k次。限速这些注释定义了可由单个客户端IP地址打开的连接的限制。这可用于缓解DDoS攻击。nginx.ingress.kubernetes.io/limit-connections:来自单个IP地址的并发连接数。 nginx.ingress.kubernetes.io/limit-rps:每秒可从给定IP接受的连接数。 nginx.ingress.kubernetes.io/limit-rpm..._ingress nginx速率限制

Jenkins 报错ssh executable not found. The git plugin only supports official git_java.lang.runtimeexception: ssh executable not fou-程序员宅基地

文章浏览阅读575次。今天用jenkins 构建job一直报错:分析:ssh executable not found. The git plugin only supports official git client http://git-scm.com/download/win的报错,可能与git --version一直打印不出来版本有关。检查Jenkins中git路径看起来没什么问题,D:\work\git_latest\Git\git-bash.exe直接复制粘贴到文件路径也能打开git。然而,实际上这个路径配_java.lang.runtimeexception: ssh executable not found. the git plugin only su

Android CE DE加密小结_android de ce-程序员宅基地

文章浏览阅读4.4k次,点赞3次,收藏16次。1.全盘加密 数据在空闲的时候进行加密 每个设备只有一个用户可以被全盘加密进行保护 那个用户在做任何工作前必须登录 2.文件级别加密 使用ext4文件系统 使用AES-256方式对文件内容进行加密 文件名也需要进行加密 文件级别加密的性能要稍微好于全盘加密f2fs文件系统用于支持nand flashDE(device en..._android de ce