OO第一单元总结-多项式求导

一、第一、第二次作业总结

  因为前两次作业设计复杂度差别不大,因而放在这里统一总结。

基于度量分析程序结构:

前两次作业确实存在缺乏可拓展设计的构想,基本还是面向过程的思维方式。“一类到底,一main到底”,因为有代码风格的要求被迫将代码模块化(捂脸)。

初次接触正则表达式,第一次设计正则表达式的时候并不知道正则的内部实现,出现了“一个大正则”,后来了解到许多正则匹配模式(贪婪,懒惰,独占)。两次作业都改成了小正则匹配同时捕获,这样可以有效避免正则爆栈的问题。

String expon = "[\\t ]*(\\^[\\t ]*[+-]{0,1}\\d{1,}){0,1}[\\t ]*";//指数
String subterm = "([\\t ]*(\\*[\\t ]*" + //后续表达式
"(((cos[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|" +
"(sin[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|x)" +
expon + "|([+-]{0,1}\\d{1,}[\\t ]*))))*";
String regax1 = "([\\t ]*\\d{1,}[\\t ]*" + subterm +
"|([\\t ]*((cos[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|" +
"(sin[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|x)" +
"(" + expon + subterm + "|" + subterm + ")" + ")" +
"|([\\t ]*[+-]\\d{1,}" + subterm + ")" +
")";
String regex = "([\\t ]*[+-][\\t ]*" + //表达式开头
"((((cos[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|(sin[\\t ]*\\([\\t ]*x[\\t ]*\\)[\\t ]*)|x)" + expon + subterm + ")" +
"|([+-]" + regax1 + ")" +
"|(\\d{1,}[\\t ]*" + subterm + ")" +
")[\\t ]*)";

  设计正则表达式时,我运用了简单的树结构,因为每个项的第一个因子较为特殊,所以单独设计,每个项的后续因子具有重复性,所以统一设计。(其实就是暴力列举所有情况)

  求导处理方面,因为没有很好考虑到可拓展性,简单的暴力求导,公式如下:

     $(ax^bsin(x)^ccos(x)^d)′=abx^{b-1}cos(x)^dsin(x)^c+acx^bcos(x)^{d+1}sin(x)^{c−1}−adx^bcos(x)^{d−1}sin(x)^{c+1}$

  存储方面,利用Arraylist存储每一个项,每个项内存储各个因子的指数。因为后来才解了Hashmap,发现对于前两次作业,Hashmap比ArrayList合并时有更大优势。

程序bug分析

  bug主要存在于输出方面的,因为优化时想去除常数因子为0的项,因为考虑不周,所以出现+0无输出的bug。

发现别人bug的策略

  1、聚焦于WF检测,根据自己设计的正则反向构造许多反例,但是发现大家WF写的都很好,确实难顶。

  2、设计一些边缘数据,比如0*sin(x)^0。(在我那个组基本没用,大家都统一设计,未发现刁钻数据一刀hack1人以上)

  3、借别人的数据来测·····难顶

  4、写了个shell脚本,能用操作系统的知识解决一次测一组人的实际需求(太顶了)

二、第三次作业总结

  这次作业简直就是地狱,周五发指导书,本来还想沿用前两次的正则构造思想,大量查阅资料,发现要递归定义正则(自己定义自己),实在是写不出来,放弃了这个选择。周六周天毫无头绪,周一了解到了一个递归下降的算法,看懂代码之后本来想拿来主义变成自己的,但是无奈自己无法复现如此精妙的递归下降,周二凌晨3点重构,从头开始。

本次作业主要分成两个工作:

  1、WF判断,这一部分我并不想前两次,在处理之前就判断,而是考虑到括号的递归存在,所以在处理时如果不符合简单小正则规范,则输出WF(在这之前有“错误符号检测”“空格及制表符模式检测”“+-符号个数检测”)。

  2、求导,针对这次作业十分复杂的特性,使用递归求导:

    1)、Poly求导结果为Poly中的Term求导相加

    2)、Term求导为Term中每个Factor求导后与剩余所有Factor相乘;

    3)、Factor求导分为5大类:x、sin(x)、cos(x)、constant、Polyfactor,其中Polyfactor求导遵循1)规则

  表达式处理是我认为本次作业最难的部分,我采用的(借鉴的)办法是,用+将Poly分成Term(在这之前用栈的方式,标记处于每个Term外的+,将Term内的+换成别的符号),然后用*将Term分成Factor(分成Factor过程分为5类,同时进行简单小正则WF判断),进而求导。(这里注意,在求导前,所有构造已经完成,即已经将所有表达式因子(Polyfactor)拆分成新的Term)

  (Poly和Term之间不存在继承关系,Factor与其他5个因子均为继承关系)

三、说说自己的理解

  以上即为我的方法(借鉴吸收别人的方法),下面我想重点介绍我理解的(仅仅个人理解,欢迎大牛指导批评),仅针对本题的递归下降算法:

  递归下降算法在本题主要针对于表达式处理,因为代码版权属于别人(我真菜),就不贴代码了,简单介绍一下:

    1)、各个类的构造办法比较平凡,和我的办法中类的构造大同小异。

    2)、在判定表达式WF中(前提是已经进行了“无效字符检查”“空格格式检查”),采用的方式是将问题下放,在最终的各个因子中进行“小正则”的简单检查。

      eg:sin((x)

      整体方法:调用toPoly()方法,toPoly()方法中调用toTerm()方法,toTerm()方法中调用toFactor()方法,toFactor()方法先检测到这属于sin类,判断“sin(” 是否存在且合法,然后跳过,接着对于中间的部分进行toFactor()方法继续构造(根据定义,sin括号内必须为一个5种因子(constant,sin,cos,x,Polyfactor)中的一种),接着回到toFactor()方法,检测后面的“)”,即完成了Sin(Factor)检查,(至于Factor是否合法,那是Factor的事)。

      追踪本eg:toFactor()方法,判断“sin(” 存在且合法后,跳过“sin(”,接着对于中间的部分使用toFactor()方法继续构造,在toFactor中发现了一个‘(’,因此判断它为一个Polyfactor类型的Factor,继续调用toPolyFactor()方法,toPolyFactor()方法构造完毕(结果为取出了“(x)”)后返回至最初的toFactor()方法检查最后的“)”,发现没有这个“)”,因为已经将“)”匹配给了里面的“(x)”,进而抛出异常,输出WF。

    3)、这种方法我读懂之后让我惊叹大自然的鬼斧神工(还有自己真菜)。个人认为它的精妙之处在于,他不关注顶层Poly如何构造,只需要知道Poly是一个一个Term构成的;同时也不需要知道Term怎么构造,因为它是一个一个Factor构成的。所有所有的问题只存在于,如何写出正确的Factor构造(这相对简单很多啊)。所有表达式提取问题迎刃而解。

    看完这份代码,我感觉到自己的渺小与可怜兮兮。仅仅针对本题,我认为这个递归下降的思想也许蕴含了面向对象的很多道理,不关心大问题的具体实现,只关心大问题可以由解决哪些小问题来解决,然后利用对象或方法来解决小问题,在这点上,差不多是我第三次作业的最大收获了。

(默默感谢对我提供帮助的大牛们)

OO第一单元总结-多项式求导的更多相关文章

  1. OO第一单元总结——多项式求导

    第一次作业分析 1.程序结构分析 类图: 好吧,这一次基本上完全是在面向过程编程,没有看出来任何的面向对象的特性. 复杂度: 可以看到模块间的相互耦合度很高,PolyDerive方法的非结构化程度也不 ...

  2. 2020 OO 第一单元总结 表达式求导

    title: BUAA-OO 第一单元总结 date: 2020-03-19 20:53:41 tags: OO categories: 学习 OO第一单元通过三次递进式的作业让我们实现表达式求导,在 ...

  3. 2019年北航OO第一单元(表达式求导任务)总结

    2019面向对象课设第一单元总结 一.三次作业总结 1. 第一次作业 1.1 需求分析 第一次作业的需求是完成简单多项式导函数的求解,表达式中每一项均为简单的常数乘以幂函数形式,优化目标为最短输出.为 ...

  4. 2019 OO第一单元总结(表达式求导)

    一. 基于度量的程序结构分析 1. 第一次作业 这次作业是我上手的第一个java程序,使用了4个类来实现功能.多项式采用两个arraylist来存,系数和幂指数一一对应. private ArrayL ...

  5. OO第一单元作业——魔幻求导

    简介 本单元作业分为三次 第一次作业:需要完成的任务为简单多项式导函数的求解. 第二次作业:需要完成的任务为包含简单幂函数和简单正余弦函数的导函数的求解. 第三次作业:需要完成的任务为包含简单幂函数和 ...

  6. OO第一单元总结——表达式求导

    第一次作业 (1) UML结构图 (2)结构分析 Polynomial 类是对输入的字符串进行预处理,其中包括判断格式是否合法,运算符简化,分割成项等方法. Polynomial处理后得到的每一个项的 ...

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

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

  8. OO第一单元作业总结——表达式求导

    OO第一单元作业总结 第一次作业 基于度量分析代码结构 基本算法 第一次作业是简单多项式导函数求解,不需要对输入数据的合法性进行判定, 基本思想是用 (coeff, expo)表示二元组 coeff* ...

  9. OO_多项式求导_单元总结

    概述: 面向对象第一单元的作业是三次难度依次递增的多项式求导.第一次作业是仅包含带符号整数和幂函数的多项式求导,例如:-1+xˆ233-xˆ06:第二次是在前面的基础上增加了三角函数的求导,例如:-1 ...

随机推荐

  1. 【LeetCode】2020-04 每日一题

    8. 字符串转换整数 (atoi)(中等) [分类]:模拟.正则表达式 [题解]: 解法1:直接模拟,但是在判断INT_MAX和INT_MIN上需要注意,因为直接判断会超出范围,所以可以将式子转换一下 ...

  2. 振兴中华(蓝桥杯13年第四届省赛真题 JAVA-B组)

    思路:因为只能横向或纵向跳到相邻的格子里,所以到'华'字有两种方法:①从左边的中横向跳过来 ②从上边的中纵向跳过来 直接递推即可. 标题: 振兴中华 小明参加了学校的趣味运动会,其中的一个项目是:跳格 ...

  3. ch1_6_1求解两种排序方法问题

    考拉有n个字符串字符串,任意两个字符串长度都是不同的.  考拉最近学习到有两种字符串的排序方法:   1.根据字符串的字典序排序.例如: "car" < "carr ...

  4. 力扣 - 剑指 Offer 09. 用两个栈实现队列

    目录 题目 思路 代码 复杂度分析 题目 剑指 Offer 09. 用两个栈实现队列 思路 刚开始想的是用stack1作为数据存储的地方,stack2用来作为辅助栈,如果添加元素直接push入stac ...

  5. PAT (Basic Level) Practice (中文)1065 单身狗 (25 分) 凌宸1642

    PAT (Basic Level) Practice (中文)1065 单身狗 (25 分) 凌宸1642 题目描述: "单身狗"是中文对于单身人士的一种爱称.本题请你从上万人的大 ...

  6. 从阿里云迁移分布式redis实例到华为云解决方案(详细)

    如果要换多数是经济因素啦- 一. 准备工作 先在华为云上买一台redis数据库,配置一定要注意多数要保持一致,至于4.0还是5.0倒问题不大亲测兼容 可用区要找现有ECS云主机中的相同的机器.记下:这 ...

  7. 配置redis 4.0.11 集群

    配置redis 4.0.11 集群 准备redis 软件和redis配置文件 启动Redis服务 /data/soft/redis/src/redis-check-aof --fix /log/red ...

  8. CrashLoopBackOff的解决办法之一

    问题来源 # kubectl get pods -n assembly NAME READY STATUS RESTARTS AGE alertmanager-858b7749c5-6jsfh 0/1 ...

  9. PhpStorm/WebStorm实用技巧

    我常用的IDE设置和功能 1) 使用IDE管理远程主机 Tools -> Deployment -> Browse Remote Host 其中功能十分强大 自己去探索 关键提示: 手动/ ...

  10. OGG-集成模式抽取与数据库参数streams_pool_size关系

    一.学习目标 Oracle数据库,使用OGG集成模式抽取进程启动时,如果没有配置合理的streams_pool_size参数可能会过一段时间就报错abend! 那么我们如何配置这个参数的大小?如何计算 ...