• 第一单元作业总结


    第一次作业

    题目要求

           第一次作业要求实现简单的多项式求导计算,且保证输入格式一定正确。

    实现思路

      使用Item类来作为“项”,其中包含coef(系数)和index(指数)两个属性,这两个属性可以确定一个“项”。然后我用Poly类来作为“多项式”,维护一个Item类型的集合,多项式即代表集合中所有项相加。还有一个Regex类用来将输入的字符串解析为一个Poly对象。最后是MainClass类,在其main方法中将输入、解析、求导、输出这一过程串联起来。

    UML类图如下:

     

    多项式的化简,只需要关注一些特定的点就可以:同类项合并,零不输出,乘1省略,第一项放正项等等。

    代码度量分析

    Type Name

    NOF

    NOPF

    NOM

    NOPM

    LOC

    WMC

    NC

    DIT

    LCOM

    FANIN

    FANOUT

    Item

    2

    0

    11

    11

    92

    24

    0

    0

    0.181818

    0

    0

    MainClass

    0

    0

    1

    1

    17

    1

    0

    0

    -1

    0

    0

    Poly

    1

    0

    6

    6

    62

    13

    0

    0

    0

    0

    0

    Regex

    11

    0

    10

    10

    128

    18

    0

    0

    0.4

    0

    0

    Bug

    第一次作业在强测中被找出bug,是正则表达式在匹配时产生了栈溢出。我是用一个正则表达式对整个式子进行匹配,其中用到了“*”使得匹配过程变得艰难。后来发现在我的正则表达式的逻辑中,完全可以将“*”变成“?”,能产生同样的效果,效率却大大提升,也不会再产生栈溢出错误。

    找别人bug的时候,一开始我还不会用sympy,而是用java做了一个”测试房间”,用来产生数据---用此数据测试屋内所有人的代码---用自己写的Regex类将他们的输出解析为Poly对象---比对这些Poly对象有没有和自己不同的。如果一个测试数据只有1-2人与自己不同,那么大概率是他们错了;如果所有人都和我不同,那就是我错了。

    反思

           在第一次作业中,我将空格出现的所有情况都写在了正则表达式里。后来从同学那里学到了预处理的方法,一开始去掉所有空格,把连续的+-号化为1个等等,觉得自己之前的办法太累赘了。后来预处理的方法用到了作业二中。

    第二次作业

    题目要求

           第二次作业在第一次作业的基础上,加入了sin和cos,且不保证输入格式正确。

    实现思路

    正余弦的计算较为简单,只需要在原来Item类中加入sinIndex和cosIndex两个属性。检验格式也好办,因为不会出现因为空格而导致的WF,所以只需要先去掉所有空格,然后用一整串正则表达式来匹配;对于幂次的限制,只需要在解析字符串的过程中,发现幂次超值,抛出异常。难点在于表达式的化简,因为三角函数变换规则较为灵活,不像作业1有唯一确定的化简道路。

           相比于作业1,新填加了Simplify类用来完成化简工作,SimplifyRule接口,以及SimplifyRule1和SimplifyRule2两个实现SimplifyRule接口的具体化简规则。UML类图如下:

     

    化简

    第二次作业的化简,使用了深搜+熔断来实现。首先有两个化简规则,1:;2:。对当前的多项式,检验每两项是否可以用规则1或规则2进行变形,如果可以,那么进行变形,并沿此搜索下去。使用一个HashMap来记录已经得到过的表达式,并通过minPoly和minPolyLength来记录当前得到的所有表达式中最短的表达式和它的长度。如果变形后的表达式在HashMap中能找到对应,说明之前得到过了,那么回溯。每得到一个表达式,比较是否比minPoly更短,短的话将minPoly更新为当前表达式。设置了最长的搜索时间和最深递归层数,如果超过时间,那么不再搜索,输出minPoly即可。

    代码度量分析

    Type Name

    NOF

    NOPF

    NOM

    NOPM

    LOC

    WMC

    NC

    DIT

    LCOM

    Item

    4

    0

    23

    23

    205

    52

    0

    0

    0

    MainClass

    0

    0

    1

    1

    24

    2

    0

    0

    -1

    Poly

    1

    0

    10

    10

    76

    20

    0

    0

    0

    Regex

    15

    0

    13

    13

    151

    24

    0

    0

    0.307692

    Simplify

    6

    0

    4

    4

    64

    16

    0

    0

    0.5

    SimplifyRule

    0

    0

    2

    2

    4

    2

    0

    0

    -1

    SimplifyRule1

    5

    0

    3

    3

    48

    5

    0

    0

    0

    SimplifyRule2

    5

    0

    3

    3

    74

    10

    0

    0

    0

    Bug

    第二次作业依然是在强测中被找出bug,bug是由垂直制表符引起的,我没有输出WF。后来才知道,java正则里的s不只代表空格,而是代表了、、、等空白符号。之后将“s”改为“ ”解决了bug。

    找别人bug,使用了sympy进行自动测试,使用xeger产生测试数据。将发现的bug保存到单独的文件中。

    反思

    如果到了后边,表达式形式变得更自由,尤其是如果出现嵌套的情况,使用“三元组“就不太好办了。果然,第三次作业出现了嵌套,于是不得不重构了……..

    第三次作业

    题目要求

    在第二次作业的基础上,加入了表达式因子;对空格格式的正确性不再保证。

    实现思路

           因为有了嵌套,所以原来三元组的思路不能使用了。进行了重构。Term接口,内部定义了求导、变号、合并等方法。常数项ConstTerm、幂函数项PowerTerm、三角函数项TrigTerm、连加项PlusTerm、连乘项MulTerm实现Term接口,而SinTerm和CosTerm继承TrigTerm。在可能会嵌套的地方,比如sin(),在SinTerm里存一个Term表示嵌套的内容。

           如此管理数据,相当于建立了一颗树,那么使用递归完成求导操作。

           由于对空格格式的正确性不再保证,所以不可以一开始去掉所有空格,必须先验证格式正确性,再去空格。于是把格式验证分开进行。首先单独验证空格格式的正确性,因为指导书已经给出空格格式错误的所有情况,所以只需遍历这些情况,只要中了一条,就抛出异常,只有顺利通过检测,才删掉字符串中所有空格,进行下一步。

           字符串解析在Analysis类中完成。由于含有嵌套括号,所以首先将每个最外层括号包含的内容,替换为特殊符号@,然后对替换后的字符串用正则来匹配。接下来使用递归解析每个@所代表的表达式。

      初始化和解析类的类图如下:

    代码度量分析

    Type Name

    NOF

    NOPF

    NOM

    NOPM

    LOC

    WMC

    NC

    DIT

    LCOM

    FANIN

    FANOUT

    MainClass

    0

    0

    1

    1

    25

    1

    0

    0

    -1

    0

    3

    ConstTerm

    2

    1

    10

    10

    58

    14

    0

    1

    0.3

    8

    3

    CosTerm

    1

    1

    9

    9

    107

    21

    0

    2

    0.666667

    3

    6

    MulTerm

    4

    1

    14

    13

    258

    58

    0

    1

    0.142857

    6

    5

    PlusTerm

    2

    1

    13

    13

    126

    32

    0

    1

    0.230769

    3

    5

    PowerTerm

    2

    1

    9

    9

    78

    17

    0

    1

    0.333333

    3

    5

    SinTerm

    1

    1

    9

    9

    104

    21

    0

    2

    0.888889

    3

    6

    Term

    0

    0

    6

    6

    15

    6

    5

    0

    -1

    10

    1

    TrigTerm

    2

    0

    5

    5

    23

    5

    2

    1

    0.6

    0

    1

    Analysis

    19

    0

    7

    7

    190

    35

    0

    0

    0

    2

    10

    MyString

    3

    0

    3

    3

    56

    11

    0

    0

    0

    1

    0

    PreTreat

    12

    0

    5

    5

    97

    17

    0

    0

    0.4

    2

    1

    Resource

    7

    7

    0

    0

    16

    0

    0

    0

    -1

    7

    2

    Bug

    本次作业被测出来的bug是,输入在cos、sin里面的表达式因子没有再嵌一层括号的时候,我没有检测出来格式错误。

    找别人bug的时候,是自己构造一些特殊数据来hack。

    反思

      凡事要提前做,不要拖到最后。我这次提交前一小时又改了些东西,结果最后提交得非常仓促。

           我将解析每种类型因子的解析方法都放在了Analysis类中,使得每次改动其中一个解析方法时,都需要满文件上下翻。如果要添加更多的因子类型(虽然后续不再有求导的作业了),就必须得在Analysis里面增加代码,这违背了开放-封闭原则。我认为更好的办法是,为每一种因子单独建立一个解析类,只负责对本因子的解析。改动一个因子的解析,只需要进入相应的类进行改动;增加一个因子,也只需增加因子类和解析类即可。和“工厂方法模式“类似。

  • 相关阅读:
    about paper
    虚拟环境部署过程中遇到的问题
    201621123028《Java程序设计》第4周学习总结
    Linux C 数据结构 ->单向链表<-(~千金散尽还复来~)
    Spring 解析(获取)URL 参数
    【简单】罗马数字转整数
    【简单】字符串字母数统计
    MongoDB 集合(collection)常用方法 (Method)
    python中group()函数的用法
    requests库
  • 原文地址:https://www.cnblogs.com/wangyiou/p/12542509.html
Copyright © 2020-2023  润新知