北航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

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范