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

智能推荐

Xcode Undefined symbols 错误_xcode undefined symbols:-程序员宅基地

文章浏览阅读3.4k次。报错信息error:Undefined symbol: typeinfo for sdk::IConfigUndefined symbol: vtable for sdk::IConfig具体信息:Undefined symbols for architecture x86_64: "typeinfo for sdk::IConfig", referenced from: typeinfo for sdk::ConfigImpl in sdk.a(config_impl.o) _xcode undefined symbols:

项目05(Mysql升级07Mysql5.7.32升级到Mysql8.0.22)_mysql8.0.26 升级32-程序员宅基地

文章浏览阅读249次。背景《承接上文,项目05(Mysql升级06Mysql5.6.51升级到Mysql5.7.32)》,写在前面需要(考虑)检查和测试的层面很多,不限于以下内容。参考文档https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.htmllink推荐阅读以上链接,因为对应以下问题,有详细的建议。官方文档:不得存在以下问题:0.不得有使用过时数据类型或功能的表。不支持就地升级到MySQL 8.0,如果表包含在预5.6.4格_mysql8.0.26 升级32

高通编译8155源码环境搭建_高通8155 qnx 源码-程序员宅基地

文章浏览阅读3.7k次。一.安装基本环境工具:1.安装git工具sudo apt install wget g++ git2.检查并安装java等环境工具2.1、执行下面安装命令#!/bin/bashsudoapt-get-yinstall--upgraderarunrarsudoapt-get-yinstall--upgradepython-pippython3-pip#aliyunsudoapt-get-yinstall--upgradeopenjdk..._高通8155 qnx 源码

firebase 与谷歌_Firebase的好与不好-程序员宅基地

文章浏览阅读461次。firebase 与谷歌 大多数开发人员都听说过Google的Firebase产品。 这就是Google所说的“ 移动平台,可帮助您快速开发高质量的应用程序并发展业务。 ”。 它基本上是大多数开发人员在构建应用程序时所需的一组工具。 在本文中,我将介绍这些工具,并指出您选择使用Firebase时需要了解的所有内容。 在开始之前,我需要说的是,我不会详细介绍Firebase提供的所有工具。 我..._firsebase 与 google

人体红外传感器HC-SR501_hc sr501工作原理-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏18次。本文记录的是如何用stm32使用HC-SR501。实验平台:野火指南者stm32f103vet6。实验现象:一旦有人体经过,LED会亮红色。HC-SR501 传感器工作原理人体都有恒定的体温,一般在 37 度,所以会发出特定波长 10UM 左右的红外线,被动式红外探头就是靠探测人体发射的 10um 左右的红外,进行工作的。人体发射的 10um 左右。_hc sr501工作原理

微信小程序云开发之创建数据库表和初始化云环境_微信云开发 自动创建表-程序员宅基地

文章浏览阅读1w次,点赞4次,收藏59次。微信小程序云开发创建数据库表1.进入小程序后点击云开发,开启云开发功能。2.开启云开发功能后会进入云开发控制台后点击左上角的数据库,后点击下面的“+”创建数据表。表名随便取,你开心就好,我的表名叫testDatabase。2.创建完表后,点击右侧的“+添加记录”会弹出一个弹窗,这个弹窗就是填写你所需要的字段。看你需要自己定义字段名,字段类型和值。3.一次只能创建一条数据,且每次创建每一条数据的字段名和类型必须一样。创建完后每一条数据都会多一个“_id”字段,这是云开发数据库自动给_微信云开发 自动创建表

随便推点

VB.net学习笔记(十五)继承与多接口练习_vb.net 继承多个接口-程序员宅基地

文章浏览阅读3.2k次。Public MustInherit Class Contact '只能作基类且不能实例化 Private mID As Guid = Guid.NewGuid Private mName As String Public Property ID() As Guid Get Return mID End Get_vb.net 继承多个接口

【Nexus3】使用-Nexus3批量上传jar包 artifact upload_nexus3 批量上传jar包 java代码-程序员宅基地

文章浏览阅读1.7k次。1.美图# 2.概述因为要上传我的所有仓库的包,希望nexus中已有的包,我不覆盖,没有的添加。所以想批量上传jar。3.方案1-脚本批量上传PS:nexus3.x版本只能通过脚本上传3.1 批量放入jar在mac目录下,新建一个文件夹repo,批量放入我们需要的本地库文件夹,并对文件夹授权(base) lcc@lcc nexus-3.22.0-02$ mkdir repo2..._nexus3 批量上传jar包 java代码

关于去隔行的一些概念_mipi去隔行-程序员宅基地

文章浏览阅读6.6k次,点赞6次,收藏30次。本文转自http://blog.csdn.net/charleslei/article/details/486519531、什么是场在介绍Deinterlacer去隔行处理的方法之前,我们有必要提一下关于交错场和去隔行处理的基本知识。那么什么是场呢,场存在于隔行扫描记录的视频中,隔行扫描视频的每帧画面均包含两个场,每一个场又分别含有该帧画面的奇数行扫描线或偶数行扫描线信息,_mipi去隔行

ABAP自定义Search help_abap 自定义 search help-程序员宅基地

文章浏览阅读1.7k次。DATA L_ENDDA TYPE SY-DATUM. IF P_DATE IS INITIAL. CONCATENATE SY-DATUM(4) '1231' INTO L_ENDDA. ELSE. CONCATENATE P_DATE(4) '1231' INTO L_ENDDA. ENDIF. DATA: LV_RESET(1) TY_abap 自定义 search help

Vue用Export2Excel导出excel,多级表头数据_vue导出为多级表头的excel-程序员宅基地

文章浏览阅读5k次,点赞12次,收藏39次。VUE 使用Export2Excel导出数据,以及多级表头最近公司做项目,需要导出数据到excel表格使用到了 element UI ,Export2Excel特此记录,毕竟好记性不如烂笔头不包含修改样式(菜鸟一枚,希望大佬指教点名)直接上代码导出单级表头Html部分:<el-button @click="handleDownload" class="addButton-class">批量导出</el-button>js部分:// 导出数据handleDo_vue导出为多级表头的excel

一次实战中对tp5网站getshell方式的测试-程序员宅基地

文章浏览阅读711次。0x00 前言之前接触tp5的站比较少,只知道利用RCE漏洞getshell的方式。在最近对一个发卡平台渗透的过程中,由于php版本限制,无法直接使用RCE的payload拿shell,于是结合该网站尽可能多的测试一下tp5+php7.1环境下的getshell方法。0x02 正文拿到站点后,访问首页如下测试中,发现是thinkphp的站,报错如下不过看不出来具体版本,不确定是否存在RCE,于是...__method=__construct&method=get&filter[]=call_user_func≥t[]=phpinfo

推荐文章

热门文章

相关标签