第一单元OO作业总结

第一次作业

​ 第一次作业的要求是对仅有常数和幂函数的式子进行求导。

​ 由于是第一次接触JAVA,对很多东西都还不熟悉,尤其是正则表达式做得不好。当时我的思路如下:

  • 建立Poly类,存储若干个幂函数(但是没有把幂函数建立成一个对象,对后面产生了麻烦)
  • 先对字符串进行预处理(好坏参半)
  • 使用符号作为关键字对原字符串进行分割(好坏参半,原因见后文分析)
  • 对特殊符号采用了保护符(有效,但是不够巧妙)
  • 进行简单判断之后,把大部分异常交给BigInteger处理(好)
  • 在Poly类中,使用Hashmap来进行合并同类项

程序思路分析&更优的思路分析

​ 这一次作业中,我有许多做得不够好的地方。可以说很多问题是不会正则表达式所导致的

对项的分割:

​ (较优的解决方案):

​ 写一个通项的正则表达式,(注意第一项和后续项的区别)。然后疯狂match,如果发现有连续匹配到的两项无法连接,或者出现了字符串前后未匹配,则抛出异常。

​ (当时我用的比较傻的方案):

​ 使用+-号作为字符串分割的关键字,调用String自带函数完成分割。但是同时产生了问题,第一个问题是指数中的符号如何处理。我的解决方案是在预处理时,将这样的符号替换成特殊字符A和S,也就是之前说的符号保护

​ 对于连续的加号减号问题,也是用字符串替换来进行化减。但是直接把形如“+ +”给换成“+”会出现问题,因为“+ +【空格】1“不合法,而”+【空格】1“合法,所以直接替换之后可能出现问题。所以再次需要使用到符号保护问题。

对格式错误的处理

​ 完成了字符串的分割之后,基于实现方法的不同,会有两种不同的情况:

​ (使用正则去判断):

​ 到这一步基本不会存在非法情况了,因为能匹配进来的字符串都是合法公民(笑)

​ (使用符号分割):

​ 到这一步之后,我选择的是做一些基础判断,比如是否为常数。是否存在系数以及指数等,如果异常则抛出相应异常。

​ 接着,把字符串再进行分割,分隔成系数,指数部分,然后把得到的结果送给BigInteger处理,其他的格式异常全部由BigInteger构造函数内部进行判断。感觉这样的做法还是挺不错的。只要保证自己分隔方法正确,任何的格式错误均会被BigInteger给捕捉。

项的存储以及求导

​ 为了方便同类项的合并,我采取了Hashmap来进行数据的存取。采用的是<BigInteger,BigInteger>的形式。然后求导的结果是返回一个String,直接输出即可。

​ 但是这样的实现方式并不好。

更优的解决方案:

​ 将项建立为一个单独的类,实现ToString方法,实现求导方法。项的求导返回的还是一个项。多项式求导返回一个新的多项式。多项式实现ToString方法。

​ 这样子,可以在读入数据的时候,调用ToString判断数据是否正确地读入。求导之后得到的结果不会影响多项式本身。再用一次ToString即可观察求导的结果。

被发现的bug&&找bug的思路

​ 我的问题发生在做符号保护这个地方。既然符号保护,就必须要使用一些特殊的字符。而我忘记判断了原始字符串里面有无出现这些特殊字符。所以导致了被人用我的保护字符进行hack的情况。

​ 还有就是对于正则表达式不熟悉,造成[-+]写成了[-|+],然后被hack。。。。

找bug的思路:

​ 第一点是对于特殊空白字符的hack。很多同学使用了\\s来进行判断空白字符。于是。。。。正义的\v出场,hack了6个人

​ 第二个点,是出现在多个符号的情况下。形如- - x是合法的,但是有的同学就没判断得出来,认为这个格式错误。hack了2个人

​ 第三个点是,单独一个符号的问题。我的测试数据是“+”,有一个人啥都没输出,有一个人输出了0,共hack2人

​ 第四个点是,当串内为空的时候,是否补0,比如“x-x”。有的同学在这个情况下就输出空串了。。。。hack2人

利用工具对自己代码进行分析

可以看出,主要的问题存在于不会用正则表达式,造成了字符串预处理、获取系数、属于指数这三个部分特别复杂。我的bug也是在这地方产生的。所以,学好正则,减少函数复杂度很有必要。

第二次作业

程序思路分析&更优的思路分析

这一次的作业,要求我们求导的式子变得更加复杂了一点。主要是新增了sin、cos,以及由于乘法所带来的运算符素质三连问题。

对于字符串的分隔

​ 采用双重正则表达式判断:

​ 由于第一次不会正则,吃了大亏。所以这一次作业恶补了一下正则表达式。我采用正则表达式将原字符串分隔成若干个乘法项。然后在构造函数内再对乘法项进行分隔,处理。

​ 这一部分判断格式错误的逻辑是:出现前后未匹配的串,或者是前后匹配项未相连,则扔出格式错误异常

注意理解三连符号出现的原因,还有首项和后续项的区别。

对于程序结构设计

​ (我之前采用的方法:)

  • 最上层的是Poly,也就是加法式。使用ArrayList来存储若干个乘法式。

  • 每个乘法式内有三个Factor,分别是X,Sin,Cos型,还有一个BigInteger型的系数。(原本想的结构是支持扩展的,但为了优化,这里的代码特化了。)

  • 每个Factor里面有一个Type,系数,指数。

求导的时候:

  • Factor的求导函数返回Factor的Arraylist,因为型如sin(x)^2^这样的Factor,求导之后的结果会是2*sin(x)*cos(x)

,也就是可能有若干项。所以需要返回的是Arraylist

  • Term的求导是基于乘法求导法则的,即一项不求导,乘上其他项全部求导。返回的是一个Term的Arraylist
  • Poly的求导是对所有的Term分别求导,然后加入到Arraylist中。
  • 对三角函数的优化集成在AddTerm这个函数里面了。

一些感觉还不错的细节:

  • 任何级别的求导,返回的均是一个相应的对象,而不是一个String。这样可以方便求导后的化简。
  • 在添加Term或者其他东西的时候。我是用了自己写的一个函数,AddTerm。刚开始写的时候,这个函数里面就是一个对Arraylist的添加。但是在后面优化的时候,比如合并,化简。只需要对这个函数修改即可完成。

被发现的bug&&找bug的思路

被发现的bug,其实是我优化的时候犯的糊涂。我在一个函数中试图把sin^2^与cos^2^合并,但是随后紧接着又试图通过拆分另一项来与当前项进行合并。于是出现了优化--复原--优化--复原的无穷递归。

找bug的时候,我们那一组的成员都比较的坚不可摧。我是采用写一个比较复杂的式子,然后随机加入空格,或者符号来进行修改。

然后在本地,先将下载下来的代码编译。分别放入文件夹中,再编写cmd脚本来进行本地的测试。

然后就基本上是加特林突突突的过程,本地运行发现有某个代码比较异常,那么就揪出来看看。

利用工具对自己的代码进行分析

可以看出,复杂度比较高的几个点存在于对于表达式化简的部分。也就是说,其他部分都相对来说比较简单。说明我的架构还是可以接受的。

第三次作业

这一次,比较麻烦。因为出现了嵌套

最初构想的思考过程&&架构&&数据处理

架构部分

​ 对于加法项和乘法项,其实改造的时候都好说。因为都是Arraylist,往后添加就好了。问题就出现在sin,cos复合的情况。求导过程中肯定要出现链式法则,而链式法则大概是f(g(x))这样的形式,所以也就是说,一个表达式要嵌套一个表达式。

​ 既然出现了嵌套相同类型,就想到了递归算法。而什么时候停止递归下去呢?遇到基本项,比如x,sin(x),cos(x)这样的情况就停止。

​ 然后我就联想到了,可以把整个表达式建成一棵子节点不定的表达式树。他的节点有这几种类型:

  • 叶节点:

    • sin(x)
    • cos(x)
    • x
    • 常数
  • 只有一个儿子的节点
    • sin(f(x))型
    • cos(f(x))型
  • 有多个儿子的节点
    • 加法类型
    • 乘法类型

数据处理部分

​ 在正则表达式中,有一种东西叫做平衡组。使用平衡组能解决对于成对括号的匹配问题,从而把sin(f(x))之类的项给提出,以交给下一级处理。

实际遇到的问题

架构方面

前文给出的架构,实际上就是一个面向对象中的继承关系。我希望达到的目标是,向程序投喂一个String,然后程序自动判断对应的类型,建立相应类型的对象。但以我的知识无法解决(据说这个是要用工厂方法。这个我之后去学学看。。。。)

于是只能把所有类都归纳成一个Term,然后在其中定义一个Type属性,根据这个属性来判断这个对象的行为。

这也就造成了写出来的代码特别丑。

当然,也有因为时间的原因啦。我只有一天的时间去写完这作业,不敢轻举妄动。

数据处理部分

JAVA的正则表达式不支持平衡组!!!!!

既然正则不好使了,原本想过利用状态机加上递归的方法去判断并分割式子的(好像这叫做递归下降?),但是助教说不建议用状态机。并且之前自己没写过这样的东西,所以就不敢乱来。

我实际使用的是小正则判断加上for循环平衡搜索

  • 先用正则表达式判断是否为x,sin,cos(这一步我最后出了bug)
  • 如果不是,则试图采用加减法分割原表达式,分隔的时候,需要保证分隔的点之前括号是匹配的,以保证不会分割掉括号内的内容
  • 再试图按照乘法类型分割原表达式,同样要求括号匹配。
  • 如果上述尝试都无法成功,抛出无法识别类型异常

之所以我先分割加减法再分割乘除法,是因为乘法优先级更高。

被发现的bug&&找bug的思路

我的bug有两点:

  • 忘了还有一种类型是+(f(x)),少判断一种类型,直接爆炸
  • 如果出现了*++5这种情况。我的分割函数没有识别出来这个是一个格式错误

于是炸得香。强测加互测共炸了20个点。结果打了两次补丁就修完了。。。。

找bug的思路:

多层括号嵌套加上乘法

​ 如果没有对括号嵌套进行优化,如剥去外层的括号。那么多层括号很可能就直接让程序tle了。特别是加上乘法之后,深层树进行乘法运算,那酸爽。。。

一发入魂,hack了6个人

格式分隔错误

​ 这一次无法使用正则表达式了,所以也就是说,在分割字符串的时候肯定会有很多容易错的地方。

​ 我写了一个比较复杂的式子,然后在里面把能加符号的地方全部加上符号,再配合以空格。hack了2人

利用工具对自己的代码进行分析

可以看出,这一次的代码是写得真的丑。主要是我的知识无法支撑我的架构,于是只能以比较粗暴的方式去写了。所以JAVA基础知识还是要学好,以我为诫。。。

不学无术的下场——OO第一单元总结的更多相关文章

  1. OO第一单元作业总结

    oo第一单元的作业是对多项式的求导.下面就是对三次作业分别进行分析. 第一次作业 分析 第一次作业相对来讲比较简单,甚至不用面向对象的思想都能十分轻松的完成(实际上自己就没有使用),包含的内容只有常数 ...

  2. OO第一单元总结

    OO第一单元作业总结 一.前言 开学四周,不知不觉已经做了三次OO作业.事实上,每一次作业对我来说都是很大的挑战,需要花费大量的时间和精力来学习. 虽然学得很艰苦,但最后还是连滚带爬地完成了.(好惨一 ...

  3. OO第一单元优化博客

    OO第一单元优化博客 第一次作业: 合并同类项+提正系数项+优化系数指数0/1=满分 第二次作业: 初始想法 一开始是想以\(sin(x)​\)和\(cos(x)​\)的指数作为坐标,在图上画出来就可 ...

  4. 【OO学习】OO第一单元作业总结

    OO第一单元作业总结 在第一单元作业中,我们只做了一件事情:求导,对多项式求导,对带三角函数的表达式求导,对有括号嵌套的表达式求导.作业难度依次递增,让我们熟悉面向对象编程方法,开始从面向过程向面向对 ...

  5. OO第一单元(求导)单元总结

    OO第一单元(求导)单元总结 这是我们oo课程的第一个单元,也是意在让我们接触了解掌握oo思想的一个单元,这个单元的作业以求导为主题,从一开始的加减多项式求导再到最后的嵌套多项式求导,难度逐渐提高,编 ...

  6. 【作业1.0】OO第一单元作业总结

    OO第一单元作业已全部完成,为了使这一单元的作业能够收获更多一点,我回忆起我曾经在计算机组成课设中,经常我们会写一些实验报告,经常以此对实验内容反思总结.在我们开始下一单元的作业之前,我在此对OO第一 ...

  7. OO第一单元(前四周)作业总结

    OO第一单元(前四周)作业总结 OO第一单元(前四周)作业总结要求(第四次作业) 0.前言 本次博客针对的是本人学习Java的第一阶段的三次作业的作业总结 第一次作业的内容是:7-1 计算税率 (20 ...

  8. 北航OO第一单元作业总结(1.1~1.3)

    经过了三次作业之后,OO第一单元告一段落,作为一个蒟蒻,我初步了解了面向对象的编程思想,并将所学内容用于实践. 一.第一次作业 1.架构分析 本次作业需要完成的任务为简单多项式导函数的求解.表达式仅支 ...

  9. OO第一单元总结与反思

    OO第一单元总结与反思 目录 OO第一单元总结与反思 摘要 第一次作业 本次作业UML类图 本次作业度量分析 第二次作业 本次作业的UML类图 本次作业的度量分析 第三次作业 本次作业的UML类图: ...

随机推荐

  1. 第5章 Hyperledger Fabric功能

    Hyperledger Fabric is a unique implementation of distributed ledger technology (DLT) that delivers e ...

  2. Spring boot配置logback

    在application-dev.yml增加配置 配置文件的路径为 rescoures/evn/dev/logback-spring.xml <?xml version="1.0&qu ...

  3. 使用OwnCloud搭建自己的云盘

    使用OwnCloud搭建自己的云盘 1.用途 ownCloud是一款开源的私有云框架,可以通过它实现个人网盘的功能,ownCloud提供了各个平台的文件同步客户端,因此搭建好ownCloud之后即可使 ...

  4. 1080P60视频源---verilog

    1080P60视频源---verilog `timescale 1ns / 1ps ////////////////////////////////////////////////////////// ...

  5. 在CentOS 7上安装Nginx

    本教程中的步骤要求用户拥有root权限 第一步 - 添加Nginx存储库要添加CentOS 7 EPEL仓库,请打开终端并使用以下命令: sudo yum install epel-release第二 ...

  6. QT中资源文件的使用

    1.在工程中点右键,选添加文件: 在下一页中输入一个资源文件名,如uires,这样工程树下就会出现资源文件夹. 2.右键,选择“Open in Editor”打开它 3.添加或修改前缀名,前缀的作用类 ...

  7. Linux环境下使用Android NDK编译c/c++生成可执行文件

    1.安装Android NDK至Linux(Lubuntu 16) 从网上下载 android-ndk-r13b-linux-x86_64.zip,本人将其解压至/home/guanglun/work ...

  8. Windows下Mysql5.7忘记root密码的解决方法

    找到mysql5.7安装的目录,我这里是:C:\Program Files\MySQL\MySQL Server 5.7 先停止mysql服务 在服务里找到MySQL57服务,停掉它. 修改my.in ...

  9. spring jpa方法关键字转成sql

    The following table describes the keywords supported for JPA and what a method containing that keywo ...

  10. pyexecjs模块

    1,找到断点事件 2,浏览call stack 下面的代码,找到需要的值 3,F11进入方法内部 对于网站自己定义的方法,可以用py复制下来进行执行js N = function (a, b, c) ...