OO多项式求导作业总结
一、程序分析
1.1第一次作业
第一次作业是简单的多项式求导,甚至没有括号嵌套。但是,就是这个在如今看来如此简单的作业,由于俺寒假过于起飞,pre没做,正则表达式也不会(属实拉跨),一度想用c语言字符串的方式一个一个读入来解决(没想到后面需要用到这么朴素的方法,也可能是我不会正则的应用)。还是在室友的提醒下,速成了正则的皮毛,然后根据第一次上机的代码提示(第一次上机我甚至不知道要在网页上commit才算提交。。。),写了一个表面面向对象(因为有三个类。。。),实则面向过程的程序。
程序类图如下:
- MainClass
在这个主类里只做数据的输入,预处理(去掉空格,替换**,分割项)以及输出。这也算有了一丢丢面向对象??? - Poly
poly有聚的意思,我也没搞懂我这里面的方法和聚有什么关系,关系真不大,改名为Factory也许更合适。这个poly,毫不客气地面向过程,要不是有checkstyle,我恨不得一个函数写完(偷笑.jpg)。里面用正则表达式匹配每一个单项,总结出这个项的指数和系数(即term类)。然后是建了一个哈希表,以系数为key,合并同类项。 - Term
这个就是一个含有两个BigInteger 的结构体,只有get和方法,来存储系数和指数
复杂度如下图所示:
这次作业耦合度很高,ptfd的求导和输出都是在一起的。
1.2第二次作业
第二次作业是增加了三角函数因子,同时也增加了括号嵌套。对括号嵌套我采用了递归下降的处理方法,对多项式的解析仍然是采用一个多元组的 ArrayList 来存储的,求导的话仍然是对每一个多元组求导。可以说方法和第一次作业一样,只是不会用正则表达式了。
程序类图如下:
- Main
这个主类和第一次作业一样,有一点不同就是我在每一个括号的内部开头加了一个 + 号,现在来看其实没必要,单独处理一下符号就行了。然后还有就是我对最后答案的化简没有直接在求导过程中化简了,而是单独用 replaceAll 来化简,其实这对效率的提升有很大帮助。 - Poly
这个类这一次有了很大的变化。由于不会使用正则表达式了,我采用一个一个字符往下读的做法,遇到表达式因子就递归处理,其他的因子都单独写了函数处理。然后同样的解析成四元组(指数,x的幂,sin(x)的幂,cos(x)的幂)列表。求导的话对每个四元组单独处理。 - Term
四元组(指数,x的幂,sin(x)的幂,cos(x)的幂)。这次除了get和set以外有了重写的tostring函数了。算一个进步吧哈哈哈。 - Thrd
这是一个三元组(x的幂,sin(x)的幂,cos(x)的幂)。我是为了合并系数相同的同类相而准备的,用这个三元组来作为key,重写了 hashCode 和 equals ,利用 HashMap 来快速寻找以便合并。其他的优化我也是有心无力了。。。
复杂度如下:
这次怎么说呢,这个递归下降不是标准的递归下降,是我自己的方法,所以一度出现了bug。好在后面改过来了。
1.2第三次作业
无效作业,就挺难受的
第三次是在sin和cos里面有了表达式因子的嵌套,另外加了格式检查。这次作业可以说是我面向对象的一大改变,终于有对象那味了。我不再是一个 Term 了,而是弄了三个因子类,系数和x是 Nx ,然后是 Sin 和 Cos 。这些类里面都有了自己的方法,我也重写了 Clone 和 equals ,实现了一个独立自主的类。
程序类图如下:
- Main
这个函数先是对格式进行了检查,格式检查的主题架构和后面解析多项式是一样的,都是递归下降方法处理。其他的方面和之前的第二次作业一样。 - Wf
这个就是我单独写的格式检查类,采用递归下降方法,但是对于指数小于50的判断我放在了后面的处理中。 - Poly
和第二次作业一样,没有别改变。 - Exp
这次我不再是一个poly打天下了,单独将表达式列了出来,也是为了后面求导的方便。表达式有自己的添加 Term 方法,还有表达式乘表达式的方法以及一些基础的克隆等方法。它的实质没变,就是一个 Term 的 ArrayList 。 - Term
这次对数据进行了新建类的处理,所以更加集中于方法的设计。求导,相乘,克隆,特别关注了合并优化。对于三角函数,分别为两个不同的三角函数因子构造了 ArrayList 以存储不同表达式的三角函数。 - Nx
这个是x和系数的综合,单独为了系数写一个类没有必要,就把他们和在一起了。 - Sin Cos
这两个三角函数因子,由表达式因子和幂组成。引用了 Exp
程序复杂度如下:
每一个类,都有自己的求导函数和加法乘法函数。每一个求导函数返回的都是一个 Exp 统一了起来,这样就不要再去单独写项乘多项式啥的了。同时每一个类也有自己的 clone equals 以及 tostring 。
当这些类可以被称作独立的的类的时候,即他们都有自己的数据和方法且耦合度极低时,本层的求导就只需本层的特殊之处加上下层.diff就行,也不再需要考虑下层的具体过程了,这或许就是面向对象了吧。
二、BUG
第二次作业我出现了一个大bug,我的递归函数,按理来说遇到 ) 需要返回,但是我当时没想透彻,还继续往下特判了紧接着 * 的情况,导致程序不能正常返回,只能碰到字符串结束符返回。在互测的时候被hack了很多次。其实互测的时候同学如果没看我代码就不会认为我是同一个错误,所以被痛击。。。
然后互测结束我修改了代码,也正是修复这个bug使我去掉了很多冗余代码,结构也变得清晰了起来。代码行数的减少是肉眼可见的,圈复杂度 slt 函数由于直接没了,也减少了不少。
我自己是如何测自己的的程序的呢?为了不那么辛苦的调试(主要是只会printf),我是写一个功能就进行测试,这样一来,至少在这三次作业,最后测的时候我的bug很少,就很省事。
记得在判断格式的时候,我出现了一个bug,由于那个测试数据格式判断递归层数较多,我是一步一步减少递归层数,找到最少的但我又出错的那个数据。然后我对每一个递归函数,开头都加了一个: System.out.println("-->xxx"); ,结尾加上 System.out.println("xxx-->"); ,xxx就是该函数名称,箭头代表进入和出去,这样一来就较为清楚了。
不过确实我觉得我还是得学学怎么用调试功能才行。
关于如何hack他人的代码,我本人是不太想做这样的事,特别是这会使其他同学丢分。当然我明白,这样做可以激励同学写出更加完美的代码,减少bug,我认为要找同学的bug可以先测一组自己构造的边界数据。然后可以阅读其具体代码考虑其没注意到的点。
阅读他人代码是可以学到许多东西的,只可惜我看到别人的代码就头大,感觉无从下手。还是说明我对代码这一块比较生疏。不过目前我还是能够读下一整个代码,对整体有把握了,但是除了明显的bug,其他的我还是看不出什么明道,希望在之后的学习中能够多读代码,提升自己的能力。
三、从面向过程到面向对象
真正知道面向对象得是第三次作业。
第一次作业是面向过程的,然后我重写的第二次作业,由于没有理解什么是面向对象,我还是面向过程。
从第二次作业到第三次作业,虽说是重构,其实其修改量可以说是重写。我真正写出了独立的类,他们都有自己的数据与方法,都是独立的,完全去掉也不影响,也方便扩充。我也感受到了面向对象的便利之处。在我求导和得出答案字符串的时候,对于本层的求导,我只需要设计本层特有的方法,而本层求导必定涉及到下一层,例如对多项式的求导涉及到多项式的每一项,而下一层的求导结果我只需要打出 下一层.diff 即可。然后 tostring 、 clone 、equals 都可以这种方式完成,既减轻了编写代码的复杂度吗,又降低了耦合度使得增加了可扩展性。这便是我目前对面向对象的理解,希望在接下来的学习中能够加深完善我的理解,学好这门课!
四、总结与感悟
在第二次作业的时候,我们上了研讨课,有同学分享了递归下降的方法,当时课上没怎么听懂,也不好意思提问,怕又是一个我不知道大家都知道的东西(这种情况对我来说太常见了,提问只会耽误大家时间,怕了怕了)。课下我去网上搜了搜资料。嗯?编译原理?文法分析?都不会啊!我硬着头皮进去,好家伙,LL0文法,左递归处理,劝退劝退。罢了,我还是自己写吧。。。。
然后在我写这个的时候,又是十分纠结。本身JAVA也不太熟,写着写着也没底,很慌,万一折腾了好久是一个错的怎么办。(真的现在我都不晓得为什么不敢试错,怕浪费时间,明明搞别的有的没的的事情我又有的是时间。可能是想到大家都会都写完了只有自己不会着急吧。。。唉,我对自己也挺无语的)别的事情我都挺头铁的,一到学习我就畏畏缩缩,不敢尝试,害怕犯错。
想想写写改改,抱着准备重写的心态运行了一下,哎,可以运行呐。自己再看了一下自己的代码,当然可以运行啊!咱也不知道啥是递归下降,就用我这个吧,递归下降怎么说呢,终究是无缘吧!??
后面我才发现原来有讨论区,原来讨论区有热心的同学通俗的分享了递归下降。
我写的也是递归下降,可能这次下降我没懂是啥意思,感觉就是个递归。但终究完成了作业。
然后不得不提我的无效作业了。
上个星期的星期天,我在写完其他步骤只剩格式检查的时候(我单独写了个格式检查),感觉轻松了许多,晚上我自己首先是测了指导书给的数据,没问题。然后又针对性地构造了一组复杂的数据,测了也没问题。
于是我第一次提交,21:22,wa了两个week点。慌了,又构造了好多数据,求助室友一起构造了数据,终于找到了原因。我格式检查的时候认为三角函数里只有x和sin,cos开头才不要加括号,没想到x地幂次方也不需要加括号,改了急急忙忙交了,21:45,week点还是有一个没过。
现在知道原来常数因子也可以不要加括号。。。。
唉,忙活了三天。现在觉得其实也没多复杂,不需要搞三天之久,可当时我改一点点就有bug,然后费尽心思找bug,所以搞了三天之久。当时感觉还挺有收获,终于对面向对象有了一定地了解。
没得机会和同学互测,没得机会检验自己的化简力度,没得机会拿到基本的作业分数。
怪我没认真看指导书。当时也是大概知道要做什么了,看到有同学在群里说 sin(-x) 不合法,要改成 sin((-x)) ,便开始自己埋头苦写。
就挺失落的,直到现在我才敢(必须)再次打开我的idea看我的代码。
虽说以至少学到了知识分数不重要来安慰自己,可是各位谁不看重分数呢?谁不呢?
当时我都不想,也没有动力去继续学习java这门课了,再怎么在优化上面搞也得不会这次无效作业扣的分。
感谢助教和老师安慰了我,也感谢给我提供帮助室友同学们!
没得办法,都已经发生了,也只能通过改变自己得想法来继续前行,就很无奈。愿大家都不会遇到我这种情况(事实上应该也不会),学到知识的同时也能取得满意的成绩!
OO多项式求导作业总结的更多相关文章
- 多项式求导系列——OO Unit1分析和总结
一.摘要 本文是BUAA OO课程Unit1在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.本文第二部分介绍三次作业的设计思路,主要以类图的形 ...
- OO——求导作业总结
目录 OO--求导作业总结 程序结构的分析 第一次作业 第二次作业 第三次作业 对多项式合法性判断的讨论 程序bug的分析 未通过的互测bug bug的位置与程序结构的关系 继承和接口的使用 互测 手 ...
- OO第一单元总结-多项式求导
OO第一单元总结-多项式求导 一.第一.第二次作业总结 因为前两次作业设计复杂度差别不大,因而放在这里统一总结. 基于度量分析程序结构: 前两次作业确实存在缺乏可拓展设计的构想,基本还是面向过程的思维 ...
- BUAA_OO Summary——多项式求导问题
从C.DS.计组一路折磨过来, 几乎都在采用过程化.函数式的编程思想.初接触面向对象的项目开发,经过了三周的对多项式求导问题的迭代开发,经历了设计.coding.测评环节,算是对面向对象有了一定的认识 ...
- BUAA-OO-第一单元表达式求导作业总结
figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...
- OO_多项式求导_单元总结
概述: 面向对象第一单元的作业是三次难度依次递增的多项式求导.第一次作业是仅包含带符号整数和幂函数的多项式求导,例如:-1+xˆ233-xˆ06:第二次是在前面的基础上增加了三角函数的求导,例如:-1 ...
- OO第一单元总结__多项式求导问题
作业一.含幂函数的简单多项式的求导 (1)基于度量的程序结构分析 1. 统计信息图: 2. 结构信息图: 3. 复杂度分析 基本复杂度(Essential Complexity (ev(G)).模块设 ...
- OO第一单元总结——多项式求导
第一次作业分析 1.程序结构分析 类图: 好吧,这一次基本上完全是在面向过程编程,没有看出来任何的面向对象的特性. 复杂度: 可以看到模块间的相互耦合度很高,PolyDerive方法的非结构化程度也不 ...
- OO第一单元表达式求导作业总结
第一次作业 功能描述: 对输入的表达式进行求导计算和格式正误判断 思路: 一开始的想法是想写一个大正则找到一个通项式,通过这个多项式来判断WRONG FORMAT,结果发现正则写的总是不完善,会漏 ...
- OO随笔之魔鬼的第一单元——多项式求导
OO是个借助Java交我们面向对象的课,可是萌新们总是喜欢带着面向过程的脑子去写求导,然后就是各种一面(main)到底.各种方法杂糅,然后就是被hack的很惨. 第一次作业:萌新入门面向对象 题目分析 ...
随机推荐
- Python Cli 编写指南
Python Cli 编写指南 python实现cli 环境: python 3.8 库 python自带argparse 指南 简单示例 : cli.py import argparse def c ...
- vue3中使用vite-ts构建项目时tsconfig.json的配置
在上一次创建vue3项目在tsconfig.json中配置了文件别名以后,格式校验提示 es3什么鬼,便去看了一下tsconfig.json的配置,以此学习 { "compilerOptio ...
- jeecg 导出加批注
public static void main(String[] args) throws IOException { // 创建工作簿对象 XSSFWorkbook wb = new XSSFWor ...
- HCIP-ICT实战进阶04-ISIS原理与配置
HCIP-ICT实战进阶04-ISIS原理与配置 0 前言 IS-IS(Intermediate System to Intermediate System, 中间系统到中间系统)协议, 和OSPF一 ...
- 如何在centos7.6操作系统下安装mysql数据库
1.从mysql官网上下载自己合适mysql版本,进入mysl官网https://dev.mysql.com/downloads/mysql/5.6.html#downloads,依次点击: 2.下载 ...
- springsecurity 配置swagger
最近在学习springsecurity 安全框架,具体是什么概念在这里不一一赘述了.下面呢,咱们一起搭建一下简单的springsecurity swagger 项目感受一下. 首先初始化spring ...
- JavaScript基础知识整理(引用类型-Date)
Date Date类型可以用来保存时间,保存的日期可以精确到1970年1月1日之后或之前的100000000天. 要创建Date类型对象,可以使用new操作符加构造函数. var now = new ...
- C# 调用https接口 安全证书问题 解决方法
原文链接: https://blog.csdn.net/lizaijinsheng/article/details/127321758 说明: 如果是用https的话,由于没有证书,会报错:基础连接已 ...
- JavaScript 之 数组在内存中的存储方式(连续或不连续)
最近在纠结一个问题,就是数组这个引用类型在JavaScript 中是不是和其他语言一样开辟了一个连续的内存来存储,但是在JS 中每个元素又可以是不同的类型,这就导致了没办法用一个相同大小的存储,所以数 ...
- ESP8266开发(物联网)
使用开发板制作wifi干扰器https://www.jianshu.com/p/f064ca36ee92