面向对象课程 HW2
前言
相较于第一次作业,第二次作业进行迭代开发主要完成的功能有:
- 支持三角函数
- 支持自定义函数
括号嵌套在第一次作业中就已经实现。
整体架构
hw2 的类图如下所示:
本次迭代中主要涉及到的工作有:
- 新增了 Function 类,用于存储自定义函数的定义并作为 Parser 的属性参与解析过程。
- 在 Var 类中新增了属性 exprs,用于存储三角函数的表达式。
- 对 Expr、Term、Var 三个类新增了 equals() 方法。
- 对 Parser 类新增了 parseBracket() 用于专门解析括号,parseFunction() 用于专门解析函数。
- 对 Lexer 类增加了识别 Function 的方法:getFunction()。
- 对预处理函数进行了若干调整。
迭代思路
处理三角函数
首先,将三角函数作为一项新的属性添加到了原子项当中。
在视图中,三角函数内部包含一个表达式。判断两个三角函数是否相等即等价于判断其内部的表达式是否相等。于是对 Expr、Term、Var 三个类中添加了 equals() 方法。
解析三角函数等价于解析括号内部表达式。将解析得到的表达式添加至三角函数内即可。
并没有对三角函数作出很强的优化。仅做了类似 sin(0) 等于 0 这样的简单化简。
Function
本类是第二次作业中新增的类,用于处理、解析、调用函数。
本类主要包含构造函数和调用函数。
在构造过程中,将函数表达式进行格式化处理。举例而言:f(x,y)=sin(x**2)+y
经处理后,解析得到 sin(($0)**2)+($1)
存储进 function 的 expr 中。
在调用方法,调用流程如下:
- 识别实参列表。
- 将 $n 替换成对应的实参。
- 传回替换实参后的字符串。
自定义函数解析
在 Parser 类中新增了 parseFunction() 方法用于解析表达式中的函数。
在解析过程中,首先进行函数的调用得到替换实参后的字符串,之后对字符串进行表达式解析,再传回解析得到的表达式。
预处理
对预处理函数的主要处理有:将 cos1*( 、sin1*(、f1*( 等替换成 cos(、sin(、1*f(。
复杂度分析
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Expr.addTerm(Term) | 0.0 | 1.0 | 1.0 | 1.0 |
Expr.addTerms(ArrayList\ |
1.0 | 1.0 | 2.0 | 2.0 |
Expr.equals(Expr) | 16.0 | 5.0 | 5.0 | 9.0 |
Expr.Expr() | 0.0 | 1.0 | 1.0 | 1.0 |
Expr.Expr(ArrayList\ |
2.0 | 2.0 | 2.0 | 3.0 |
Expr.getTerms() | 0.0 | 1.0 | 1.0 | 1.0 |
Expr.toString() | 1.0 | 1.0 | 2.0 | 2.0 |
Function.call(String) | 9.0 | 1.0 | 6.0 | 7.0 |
Function.Function(String) | 1.0 | 1.0 | 2.0 | 2.0 |
Function.getExpr() | 0.0 | 1.0 | 1.0 | 1.0 |
Function.getState() | 0.0 | 1.0 | 1.0 | 1.0 |
Function.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
Lexer.getFunction() | 5.0 | 1.0 | 2.0 | 4.0 |
Lexer.getNumber() | 2.0 | 1.0 | 3.0 | 3.0 |
Lexer.Lexer(String) | 0.0 | 1.0 | 1.0 | 1.0 |
Lexer.next() | 8.0 | 2.0 | 5.0 | 7.0 |
Lexer.peek() | 0.0 | 1.0 | 1.0 | 1.0 |
MainClass.main(String[]) | 1.0 | 1.0 | 2.0 | 2.0 |
Parser.parseBracket(ArrayList\ |
4.0 | 2.0 | 3.0 | 3.0 |
Parser.parseExpr() | 2.0 | 1.0 | 3.0 | 3.0 |
Parser.parseFunction(ArrayList\ |
7.0 | 4.0 | 5.0 | 5.0 |
Parser.Parser(Lexer, ArrayList\ |
0.0 | 1.0 | 1.0 | 1.0 |
Parser.parseTerm() | 13.0 | 1.0 | 10.0 | 10.0 |
Parser.parseVar() | 23.0 | 7.0 | 11.0 | 15.0 |
Term.add(Term) | 9.0 | 3.0 | 5.0 | 7.0 |
Term.addVar(Var) | 1.0 | 1.0 | 2.0 | 2.0 |
Term.addVars(ArrayList\) | 2.0 | 2.0 | 2.0 | 3.0 |
Term.addVars(Term) | 1.0 | 1.0 | 2.0 | 2.0 |
Term.copy() | 0.0 | 1.0 | 1.0 | 1.0 |
Term.equals(Term) | 17.0 | 6.0 | 5.0 | 10.0 |
Term.getConstant() | 3.0 | 3.0 | 3.0 | 3.0 |
Term.getSymbol() | 0.0 | 1.0 | 1.0 | 1.0 |
Term.setSymbol() | 1.0 | 1.0 | 2.0 | 2.0 |
Term.setSymbol(int) | 0.0 | 1.0 | 1.0 | 1.0 |
Term.similar(Term) | 39.0 | 13.0 | 15.0 | 21.0 |
Term.simplify() | 23.0 | 5.0 | 13.0 | 14.0 |
Term.Term() | 0.0 | 1.0 | 1.0 | 1.0 |
Term.Term(int) | 0.0 | 1.0 | 1.0 | 1.0 |
Term.Term(Var) | 0.0 | 1.0 | 1.0 | 1.0 |
Term.toString() | 6.0 | 3.0 | 3.0 | 6.0 |
Tool.afterTreat(String) | 1.0 | 1.0 | 2.0 | 2.0 |
Tool.exprSimplify(ArrayList\ |
8.0 | 2.0 | 5.0 | 6.0 |
Tool.mul(ArrayList\ |
3.0 | 1.0 | 3.0 | 3.0 |
Tool.mul(Term, Term) | 0.0 | 1.0 | 1.0 | 1.0 |
Tool.preTreat(String) | 2.0 | 1.0 | 5.0 | 5.0 |
Tool.removeSpace(String) | 0.0 | 1.0 | 1.0 | 1.0 |
Var.addAbs(Var) | 2.0 | 2.0 | 1.0 | 3.0 |
Var.copy() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.equals(Var) | 5.0 | 4.0 | 3.0 | 6.0 |
Var.getCharacter() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.getExpr() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.getNum() | 1.0 | 1.0 | 2.0 | 2.0 |
Var.getSymbol() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.getType() | 0.0 | 1.0 | 1.0 | 1.0 |
Var.setSymbol(int) | 0.0 | 1.0 | 1.0 | 1.0 |
Var.simplify() | 8.0 | 4.0 | 5.0 | 8.0 |
Var.subAbs(Var) | 2.0 | 2.0 | 1.0 | 3.0 |
Var.toString() | 9.0 | 4.0 | 7.0 | 9.0 |
Var.Var(int) | 1.0 | 1.0 | 1.0 | 2.0 |
Var.Var(int, BigInteger, Character, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Var.Var(int, BigInteger, Character, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Var.Var(int, BigInteger, Character, int, int, ArrayList\ |
0.0 | 1.0 | 1.0 | 1.0 |
Var.Var(int, BigInteger, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Var.Var(int, Character, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
Total | 239.0 | 121.0 | 179.0 | 225.0 |
Average | 3.6769230769230767 | 1.8615384615384616 | 2.753846153846154 | 3.4615384615384617 |
可以看到在添加了三角函数后 Term 类的 similar 方法复杂度直接爆炸了…这主要是因为对三角函数的判断逻辑比较复杂。此外对原子项的语法解析也因为三角函数的加入而变得稍显臃肿。考虑改进的话可以将对三角函数的语法解析提取到单独的类中。
bug 分析
第二次作业的构建过程中没有遇到什么特别的 bug。强测互测也都顺利通过。
总结
第二周的压力比第一周小了很多,仿佛一切都在步上正轨,令人欣慰。虽然一度为弱智 bug 所苦恼,不过跟第一周的坐牢比起来已经幸福太多了。并且由于第一周架构比较合理(貌似是),我在本次的迭代开发的过程中并未遇到什么困难,整体架构也几乎没有变动。唯一最大的困难就是我本人捉急的码力(悲)