301
社区成员
发帖
与我相关
我的任务
分享第一单元的总任务为表达式括号展开。三次任务分别为单变量多项式展开,含指数函数与自定义函数的多项式展开,含求导因子的多项式展开。第一单元的任务目标可以总结为学习面向对象的思想,从数据与行为两个角度认识对象,并且掌握层次化设计理念。
总体上来说,由于有先导课程的铺垫以及助教们介绍的递归下降这一核心处理思想的帮助,本次作业总体上实现阻碍不大。但在输出结果优化以及一些细节上的实现仍然有一定的挑战。尤其是第一次作业到第二次作业有一定的跨度。不过最后还是顺利度过,下面是我对第一单元的总结与思考。

StringProcessing类对输入进行预处理,主要做到:删除空白项,合并连续的加减正负号,删除前导零。
表达式一共包含三层:Expr,Term, Factor。Factor有三种:幂函数, 常数函数,表达式因子。
因此,要做的就是如何将给出的表达式解析成Expr,Term, Factor。
这里使用助教们讲解过的递归下降算法。
功能:将输入分解为一个个Token。
Token:
public enum Type {
ADD, SUB, MUL, CARET,
LEFT_P, RIGHT_P,
VAR_X, NUM
}
Lexer:
while (pos < expression.length()) {
if (expression.charAt(pos) == '(') {
...
} else if (expression.charAt(pos) == ')') {
...
} else if (expression.charAt(pos) == '*') {
...
} else if (expression.charAt(pos) == '^') {
...
} else if (expression.charAt(pos) == 'x') {
...
} else if (expression.charAt(pos) == '+') {
...
} else if (expression.charAt(pos) == '-') {
...
} else {
...
}
}
Parser类的功能为将Lexer解析为三部分Expr,Term, Factor。
实现思想就是根据当前Token判断下一项是Expr,Term, Factor,Num, Power, ExprFactor。
public Expr parseExpr() {
ArrayList<Term> terms = new ArrayList<>();
...
terms.add(parseTerm(sign));
while (下一Token为Term开头) {
...
terms.add(parseTerm(sign));
}
return new Expr(terms);
}
public Term parseTerm(int sign) {
ArrayList<Factor> factors = new ArrayList<>();
factors.add(parseFactor());
while (下一Token为Factor开头) {
...
factors.add(parseFactor());
}
return new Term(sign, factors);
}
public Factor parseFactor() {
...
return new Factor();
}
| Source File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Lines | Comment Lines[%] | Blank Lines | Blank Lines[%] |
|---|---|---|---|---|---|---|---|
| Calculate.java | 83 | 75 | 0.904 | 0 | 0.0 | 8 | 0.096 |
| Constant.java | 40 | 32 | 0.8 | 1 | 0.025 | 7 | 0.175 |
| Expr.java | 20 | 16 | 0.8 | 0 | 0.0 | 4 | 0.2 |
| ExprFactor.java | 35 | 30 | 0.857 | 0 | 0.0 | 5 | 0.1429 |
| Factor.java | 3 | 3 | 1.0 | 0 | 0.0 | 0 | 0.0 |
| Lexer.java | 75 | 68 | 0.907 | 0 | 0.0 | 7 | 0.0933 |
| Main.java | 22 | 19 | 0.864 | 1 | 0.0455 | 2 | 0.091 |
| Monomial.java | 51 | 45 | 0.882 | 0 | 0.0 | 6 | 0.118 |
| Num.java | 17 | 14 | 0.824 | 0 | 0.0 | 3 | 0.17653 |
| Parser.java | 85 | 78 | 0.918 | 2 | 0.0235 | 5 | 0.0588 |
| Polynomial.java | 61 | 53 | 0.869 | 0 | 0.0 | 8 | 0.1311 |
| Power.java | 21 | 17 | 0.81 | 0 | 0.0 | 4 | 0.1905 |
| StringProcessing.java | 82 | 71 | 0.866 | 3 | 0.0366 | 8 | 0.0976 |
| Term.java | 32 | 26 | 0.813 | 0 | 0.0 | 6 | 0.1875 |
| Token.java | 24 | 19 | 0.792 | 1 | 0.0417 | 4 | 0.1667 |
| method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| Token.Token(Type, String) | 0.0 | 1.0 | 1.0 | 1.0 |
| Token.getType() | 0.0 | 1.0 | 1.0 | 1.0 |
| Token.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
| Term.toPolynomial() | 1.0 | 1.0 | 2.0 | 2.0 |
| Term.Term(int, ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| Term.setSign(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Term.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
| StringProcessing.removeLeadingZero(String) | 8.0 | 5.0 | 4.0 | 6.0 |
| StringProcessing.removeAllLeadingZero(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| StringProcessing.pretreatment(String) | 0.0 | 1.0 | 1.0 | 1.0 |
| StringProcessing.mergeAddAndSub(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| StringProcessing.merge(String) | 5.0 | 2.0 | 2.0 | 4.0 |
| Power.toPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| Power.Power(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.toString() | 1.0 | 1.0 | 2.0 | 2.0 |
| Polynomial.simplifyPolynomial() | 9.0 | 1.0 | 7.0 | 7.0 |
| Polynomial.Polynomial(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.getSize() | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.getMonomial(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.addMonomial(Monomial) | 3.0 | 3.0 | 3.0 | 3.0 |
| Parser.parseTerm(int) | 2.0 | 1.0 | 3.0 | 3.0 |
| Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
| Parser.parseFactor() | 19.0 | 5.0 | 13.0 | 13.0 |
| Parser.parseExpr() | 7.0 | 1.0 | 6.0 | 7.0 |
| Num.toPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| Num.Num(String, int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Monomial.toString() | 12.0 | 1.0 | 8.0 | 10.0 |
| Monomial.setIndex(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Monomial.setCoefficient(Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| Monomial.Monomial(Constant, int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Monomial.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
| Monomial.getCoefficient() | 0.0 | 1.0 | 1.0 | 1.0 |
| Main.main(String[]) | 2.0 | 1.0 | 2.0 | 3.0 |
| Lexer.pre() | 1.0 | 2.0 | 2.0 | 2.0 |
| Lexer.post() | 1.0 | 2.0 | 2.0 | 2.0 |
| Lexer.now() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.notEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.move() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.Lexer(String) | 21.0 | 11.0 | 10.0 | 13.0 |
| ExprFactor.toPolynomial() | 5.0 | 1.0 | 4.0 | 4.0 |
| ExprFactor.ExprFactor(Expr, int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Expr.toPolynomial() | 1.0 | 1.0 | 2.0 | 2.0 |
| Expr.Expr(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.toString() | 2.0 | 1.0 | 2.0 | 2.0 |
| Constant.getValue() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.equalZero() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.equalOne() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.Constant(int, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.mulPolynomial(Polynomial, Polynomial) | 3.0 | 1.0 | 3.0 | 3.0 |
| Calculate.mulMonomial(Monomial, Monomial) | 3.0 | 1.0 | 3.0 | 3.0 |
| Calculate.mulConstant(Constant, Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.findMonomialIndex(ArrayList, int) | 3.0 | 3.0 | 2.0 | 3.0 |
| Calculate.addPolynomial(Polynomial, Polynomial) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.addMonoToPoly(Polynomial, ArrayList) | 1.0 | 1.0 | 2.0 | 2.0 |
| Calculate.addMonoToMonoS(Monomial, ArrayList) | 2.0 | 1.0 | 2.0 | 2.0 |
| Calculate.addConstant(Constant, Constant) | 4.0 | 1.0 | 4.0 | 4.0 |
| Total | 120.0 | 82.0 | 128.0 | 140.0 |
| Average | 2.105 | 1.439 | 2.246 | 2.456 |
Lexer类中的Lexer()使用了大量的if...else...解析语法单元,结构较为冗余,代码量较大;Parser类中的ParserFactor()使用大量的if...else...分析因子类型,代码复杂度较高。
从第一次作业到第二次作业跨度较大,主要困难如下:
如何解析自定义函数,实现代值操作;
指数函数的加入导致化简后的最小单元变得复杂,从$coex^{index}$变为$coex^{index}*exp(Factor)$,toPoly()方法必然会递归地解析指数函数地指数部分,如何找到递归终点;
如何实现表达式的化简。
这一步主要靠新建的FuncCall类
这个类有两个功能。
首先,是建立自定义函数名与自定义函数表达式、自定义函数名与形参列表的一一映射关系。
然后根据调用parserFunc()后传入的自定义函数名与实参列表,得到自定义函数调用后产生的表达式字符串,再对这个字符串进行解析。
FuncCall
// 函数名 <-> 函数定义式
private static HashMap<String, String> functionDefine = new HashMap<>();
// 函数名 <-> 形参列表
private static HashMap<String, ArrayList<String>> parameters = new HashMap<>();
public static void addFunction(String input) {
...
functionDefine.put(funcName, funcDefine);
...
parameters.put(funcName, parameterMap);
}
public static Expr callFunction(FunctionFactor functionFactor) {
String expression;
...
return new Parser(new Lexer(expression)).parseExpr();
}
这里将最小单元Unit定为$coe*x^{index}*exp(Poly)$,因为Poly为Unit集合,所以调用toPoly()时必然会有递归,这里将Poly == Zero作为递归终点。
在完成第二次作业时,采用了摆烂优化法,性能分并不高。
| Source File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Lines | Comment Lines[%] | Blank Lines | Blank Lines[%] |
|---|---|---|---|---|---|---|---|
| Unit.java | 161 | 147 | 0.913 | 0 | 0.0 | 14 | 0.087 |
| Token.java | 25 | 20 | 0.8 | 1 | 0.04 | 4 | 0.16 |
| Term.java | 36 | 32 | 0.889 | 0 | 0.0 | 4 | 0.111 |
| StringProcessing.java | 93 | 81 | 0.871 | 3 | 0.0323 | 9 | 0.0968 |
| PowerFactor.java | 28 | 24 | 0.857 | 0 | 0.0 | 4 | 0.1429 |
| Polynomial.java | 58 | 51 | 0.879 | 0 | 0.0 | 7 | 0.1207 |
| Parser.java | 124 | 114 | 0.919 | 0 | 0.0 | 10 | 0.0806 |
| NumFactor.java | 26 | 22 | 0.846 | 0 | 0.0 | 4 | 0.1538 |
| Main.java | 21 | 20 | 0.952 | 0 | 0.0 | 1 | 0.0476 |
| Lexer.java | 85 | 78 | 0.918 | 0 | 0.0 | 7 | 0.0824 |
| FunctionFactor.java | 43 | 34 | 0.791 | 0 | 0.0 | 9 | 0.2093 |
| FunctionCall.java | 44 | 39 | 0.886 | 2 | 0.0455 | 3 | 0.0682 |
| Factor.java | 5 | 4 | 0.8 | 0 | 0.0 | 1 | 0.2 |
| ExpressionFactor.java | 41 | 36 | 0.878 | 0 | 0.0 | 5 | 0.122 |
| Expression.java | 27 | 23 | 0.852 | 0 | 0.0 | 4 | 0.1481 |
| ExponentialFactor.java | 30 | 26 | 0.867 | 0 | 0.0 | 4 | 0.133 |
| Constant.java | 44 | 35 | 0.795 | 0 | 0.0 | 9 | 0.205 |
| Calculate.java | 91 | 79 | 0.868 | 2 | 0.022 | 10 | 0.1099 |
| method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| Unit.Unit(Constant, BigInteger, Polynomial) | 0.0 | 1.0 | 1.0 | 1.0 |
| Unit.toString() | 3.0 | 3.0 | 2.0 | 3.0 |
| Unit.sameType(Unit) | 6.0 | 1.0 | 4.0 | 5.0 |
| Unit.oneCoefficient() | 22.0 | 1.0 | 6.0 | 10.0 |
| Unit.nomCoefficient() | 12.0 | 1.0 | 6.0 | 6.0 |
| Unit.isFactor() | 6.0 | 4.0 | 8.0 | 9.0 |
| Unit.getXIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
| Unit.getExpIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
| Unit.getCoefficient() | 0.0 | 1.0 | 1.0 | 1.0 |
| Unit.expIndexToString() | 3.0 | 2.0 | 3.0 | 3.0 |
| Unit.equals(Unit) | 6.0 | 1.0 | 5.0 | 6.0 |
| Unit.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| Unit.addCoefficient(Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| Token.Token(Type, String) | 0.0 | 1.0 | 1.0 | 1.0 |
| Token.getType() | 0.0 | 1.0 | 1.0 | 1.0 |
| Token.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
| Term.toString() | 3.0 | 1.0 | 3.0 | 3.0 |
| Term.toPolynomial() | 1.0 | 1.0 | 2.0 | 2.0 |
| Term.Term(int, ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| StringProcessing.removeLeadingZero(String) | 8.0 | 5.0 | 4.0 | 6.0 |
| StringProcessing.removeAllLeadingZero(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| StringProcessing.removeAdd(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| StringProcessing.pretreatment(String) | 0.0 | 1.0 | 1.0 | 1.0 |
| StringProcessing.mergeAddSub(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| StringProcessing.merge(String) | 5.0 | 2.0 | 2.0 | 4.0 |
| PowerFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| PowerFactor.toPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| PowerFactor.PowerFactor(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.toString() | 2.0 | 2.0 | 2.0 | 3.0 |
| Polynomial.Polynomial(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.isZero() | 3.0 | 3.0 | 2.0 | 3.0 |
| Polynomial.getUnit(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.getSize() | 0.0 | 1.0 | 1.0 | 1.0 |
| Polynomial.equals(Polynomial) | 9.0 | 6.0 | 3.0 | 6.0 |
| Parser.parseTerm(int) | 2.0 | 1.0 | 3.0 | 3.0 |
| Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
| Parser.parseFunction() | 2.0 | 1.0 | 3.0 | 3.0 |
| Parser.parseFactor() | 10.0 | 5.0 | 11.0 | 11.0 |
| Parser.parseExpression() | 7.0 | 1.0 | 6.0 | 7.0 |
| Parser.getPowerFactor() | 3.0 | 1.0 | 3.0 | 3.0 |
| Parser.getNumFactor() | 4.0 | 1.0 | 2.0 | 3.0 |
| Parser.getExpressionFactor() | 3.0 | 1.0 | 3.0 | 3.0 |
| Parser.getExponentialFactor() | 0.0 | 1.0 | 1.0 | 1.0 |
| NumFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| NumFactor.toPolynomial() | 1.0 | 2.0 | 2.0 | 2.0 |
| NumFactor.NumFactor(BigInteger, int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Main.main(String[]) | 1.0 | 1.0 | 2.0 | 2.0 |
| Lexer.pre() | 1.0 | 2.0 | 2.0 | 2.0 |
| Lexer.post() | 1.0 | 2.0 | 2.0 | 2.0 |
| Lexer.now() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.notEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.move() | 0.0 | 1.0 | 1.0 | 1.0 |
| Lexer.Lexer(String) | 25.0 | 14.0 | 15.0 | 18.0 |
| FunctionFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.toPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.toExpression() | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.newFunc() | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.getFunctionName() | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.getActualPara(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionFactor.FunctionFactor(String, ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| FunctionCall.callFunction(FunctionFactor) | 8.0 | 4.0 | 5.0 | 5.0 |
| FunctionCall.addFunction(String) | 4.0 | 1.0 | 5.0 | 5.0 |
| ExpressionFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| ExpressionFactor.toPolynomial() | 1.0 | 1.0 | 2.0 | 2.0 |
| ExpressionFactor.toIndexPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| ExpressionFactor.ExpressionFactor(Expression, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| Expression.toString() | 1.0 | 1.0 | 2.0 | 2.0 |
| Expression.toPolynomial() | 1.0 | 1.0 | 2.0 | 2.0 |
| Expression.Expression(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| ExponentialFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| ExponentialFactor.toPolynomial() | 0.0 | 1.0 | 1.0 | 1.0 |
| ExponentialFactor.ExponentialFactor(ExpressionFactor) | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.toString() | 2.0 | 1.0 | 2.0 | 2.0 |
| Constant.getValue() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.equalZero() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.equals(Constant) | 1.0 | 1.0 | 2.0 | 2.0 |
| Constant.equalOne() | 0.0 | 1.0 | 1.0 | 1.0 |
| Constant.Constant(int, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.Zero() | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.One(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.mulUnit(Unit, Unit) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.mulPolynomial(Polynomial, Polynomial) | 5.0 | 2.0 | 4.0 | 5.0 |
| Calculate.mulConstant(Constant, Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.addUnitToUnits(Unit, ArrayList) | 3.0 | 3.0 | 3.0 | 3.0 |
| Calculate.addPolyToUnits(Polynomial, ArrayList) | 1.0 | 1.0 | 2.0 | 2.0 |
| Calculate.addPolynomial(Polynomial, Polynomial) | 0.0 | 1.0 | 1.0 | 1.0 |
| Calculate.addConstant(Constant, Constant) | 4.0 | 1.0 | 4.0 | 4.0 |
| Total | 186.0 | 133.0 | 196.0 | 219.0 |
| Average | 2.114 | 1.511 | 2.227 | 2.489 |
这一次作业的代码复杂度原因与第一次一样,Lexer中大量的if...else...使得代码复杂度增大。
对于parseFactor()方法,这次进行了优化,分解成了多个方法,降低了复杂度

第三次加入了求导因子dx(Expr),并且让函数表达式可以嵌套定义。
难点总的来说就这两点,由于第二次采用的自定义函数解析方法能够实现函数表达式的嵌套定义,因此新增的相当于只有一个求导因子。
核心解决思路为对Unit的求导:
Unit:$coex^{index}exp(Poly)$,Unit求导为$indexcoex^{index}exp(Poly) + coex^{index}*exp(Poly)*Poly.derive()$。
| Source File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Lines | Comment Lines[%] | Blank Lines | Blank Lines[%] |
|---|---|---|---|---|---|---|---|
| Add.java | 51 | 46 | 0.902 | 0 | 0.0 | 5 | 0.098 |
| Constant.java | 53 | 43 | 0.811 | 0 | 0.0 | 10 | 0.1887 |
| ConstantPoly.java | 30 | 24 | 0.8 | 0 | 0.0 | 6 | 0.2 |
| DeFactor.java | 29 | 23 | 0.793 | 0 | 0.0 | 6 | 0.207 |
| ExpFactor.java | 44 | 37 | 0.841 | 0 | 0.0 | 7 | 0.159 |
| Expression.java | 41 | 34 | 0.829 | 0 | 0.0 | 7 | 0.171 |
| ExprFactor.java | 32 | 25 | 0.781 | 0 | 0.0 | 7 | 0.21875 |
| Factor.java | 11 | 7 | 0.636 | 0 | 0.0 | 4 | 0.364 |
| FuncCall.java | 47 | 40 | 0.851 | 2 | 0.043 | 5 | 0.1064 |
| FuncFactor.java | 39 | 31 | 0.795 | 0 | 0.0 | 8 | 0.205 |
| Gcd.java | 16 | 14 | 0.875 | 0 | 0.0 | 2 | 0.125 |
| Lexer.java | 91 | 82 | 0.901 | 0 | 0.0 | 9 | 0.099 |
| Main.java | 27 | 25 | 0.926 | 0 | 0.0 | 2 | 0.0741 |
| Mul.java | 34 | 29 | 0.853 | 0 | 0.0 | 5 | 0.1471 |
| NumFactor.java | 35 | 28 | 0.8 | 0 | 0.0 | 7 | 0.2 |
| Parser.java | 155 | 142 | 0.916 | 0 | 0.0 | 13 | 0.084 |
| Poly.java | 133 | 119 | 0.895 | 0 | 0.0 | 14 | 0.105 |
| Powered.java | 16 | 13 | 0.8125 | 0 | 0.0 | 3 | 0.1875 |
| PowerFactor.java | 34 | 27 | 0.794 | 0 | 0.0 | 7 | 0.2059 |
| StrProcess.java | 97 | 84 | 0.866 | 3 | 0.031 | 10 | 0.1031 |
| Term.java | 51 | 44 | 0.863 | 0 | 0.0 | 7 | 0.137 |
| Token.java | 27 | 21 | 0.778 | 1 | 0.037 | 5 | 0.1852 |
| Unit.java | 188 | 169 | 0.899 | 0 | 0.0 | 19 | 0.1011 |
| method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| poly.Unit.Unit(Constant, BigInteger, Poly) | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.toString() | 3.0 | 3.0 | 2.0 | 3.0 |
| poly.Unit.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.sameType(Unit) | 6.0 | 1.0 | 4.0 | 5.0 |
| poly.Unit.oneCoe() | 22.0 | 1.0 | 6.0 | 10.0 |
| poly.Unit.numCoe() | 12.0 | 1.0 | 6.0 | 6.0 |
| poly.Unit.isFactor() | 6.0 | 4.0 | 8.0 | 9.0 |
| poly.Unit.indexOfExpToString() | 3.0 | 2.0 | 3.0 | 3.0 |
| poly.Unit.getNewUnit(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.getIndexOfX() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.getIndexOfExp() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.getCoefficient() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.equals(Unit) | 6.0 | 1.0 | 5.0 | 6.0 |
| poly.Unit.derive() | 5.0 | 1.0 | 5.0 | 5.0 |
| poly.Unit.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Unit.addCoefficient(Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Poly.toString() | 8.0 | 4.0 | 5.0 | 7.0 |
| poly.Poly.size() | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Poly.Poly(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Poly.getNewPoly(BigInteger) | 1.0 | 1.0 | 2.0 | 2.0 |
| poly.Poly.getGcd() | 2.0 | 2.0 | 2.0 | 3.0 |
| poly.Poly.get(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| poly.Poly.expToString() | 9.0 | 4.0 | 5.0 | 6.0 |
| poly.Poly.equalZero() | 3.0 | 3.0 | 2.0 | 3.0 |
| poly.Poly.equals(Poly) | 11.0 | 7.0 | 4.0 | 8.0 |
| poly.Poly.derive() | 1.0 | 1.0 | 2.0 | 2.0 |
| poly.Poly.clone() | 1.0 | 1.0 | 2.0 | 2.0 |
| parser.Token.Token(Type, String) | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Token.getType() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Token.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.StrProcess.removeLeadingZero(String) | 8.0 | 5.0 | 4.0 | 6.0 |
| parser.StrProcess.removeAllLeadingZero(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| parser.StrProcess.preProcess(String) | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.StrProcess.postProcess(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| parser.StrProcess.mergeAddSub(String) | 2.0 | 1.0 | 3.0 | 3.0 |
| parser.StrProcess.merge(String) | 5.0 | 2.0 | 2.0 | 4.0 |
| parser.Parser.parseTerm(int) | 2.0 | 1.0 | 3.0 | 3.0 |
| parser.Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Parser.parseFactor() | 12.0 | 6.0 | 13.0 | 13.0 |
| parser.Parser.parseExpression() | 7.0 | 1.0 | 6.0 | 7.0 |
| parser.Parser.getPowerFactor() | 3.0 | 1.0 | 3.0 | 3.0 |
| parser.Parser.getNumFactor() | 4.0 | 1.0 | 2.0 | 3.0 |
| parser.Parser.getFuncFactor() | 2.0 | 1.0 | 3.0 | 3.0 |
| parser.Parser.getExprFactor() | 3.0 | 1.0 | 3.0 | 3.0 |
| parser.Parser.getExpFactor() | 3.0 | 1.0 | 3.0 | 3.0 |
| parser.Parser.getDeFactor() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Lexer.pre() | 1.0 | 2.0 | 2.0 | 2.0 |
| parser.Lexer.post() | 1.0 | 2.0 | 2.0 | 2.0 |
| parser.Lexer.now() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Lexer.notEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Lexer.move() | 0.0 | 1.0 | 1.0 | 1.0 |
| parser.Lexer.Lexer(String) | 15.0 | 5.0 | 7.0 | 9.0 |
| parser.Lexer.getType(char) | 13.0 | 12.0 | 1.0 | 14.0 |
| Main.main(String[]) | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.Term.toString() | 3.0 | 1.0 | 3.0 | 3.0 |
| expr.Term.toPoly() | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.Term.Term(int, ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Term.clone() | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.factor.PowerFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.PowerFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.PowerFactor.PowerFactor(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.PowerFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.NumFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.NumFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.NumFactor.NumFactor(int, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.NumFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncFactor.FuncFactor(String, ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncFactor.FuncFactor(Expression) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.FuncCall.funcCall(String, ArrayList) | 8.0 | 4.0 | 5.0 | 5.0 |
| expr.factor.FuncCall.addFunc(String) | 4.0 | 1.0 | 5.0 | 5.0 |
| expr.factor.ExprFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExprFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExprFactor.ExprFactor(Expression, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExprFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExpFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExpFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExpFactor.ExpFactor(Factor, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.ExpFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.DeFactor.toString() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.DeFactor.toPoly() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.DeFactor.DeFactor(Expression) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.factor.DeFactor.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Expression.toString() | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.Expression.toPoly() | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.Expression.Expression(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Expression.clone() | 1.0 | 1.0 | 2.0 | 2.0 |
| expr.Constant.toString() | 2.0 | 2.0 | 2.0 | 2.0 |
| expr.Constant.getValue() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Constant.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Constant.equalZero() | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Constant.equals(Constant) | 2.0 | 2.0 | 2.0 | 3.0 |
| expr.Constant.equalOne(int) | 3.0 | 2.0 | 3.0 | 3.0 |
| expr.Constant.Constant(int, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
| expr.Constant.clone() | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.Powered.polyPower(Poly, BigInteger) | 1.0 | 1.0 | 2.0 | 2.0 |
| calculate.Mul.mulUnit(Unit, Unit) | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.Mul.mulPoly(Poly, Poly) | 3.0 | 1.0 | 3.0 | 3.0 |
| calculate.Mul.mulConstant(Constant, Constant) | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.Gcd.gcd(BigInteger, BigInteger) | 1.0 | 1.0 | 2.0 | 2.0 |
| calculate.ConstantPoly.Zero() | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.ConstantPoly.One(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.ConstantPoly.constantZero() | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.ConstantPoly.constantOne(int) | 0.0 | 1.0 | 1.0 | 1.0 |
| calculate.Add.addUnitToUnits(Unit, ArrayList) | 3.0 | 3.0 | 3.0 | 3.0 |
| calculate.Add.addPoly(Poly, Poly) | 2.0 | 1.0 | 3.0 | 3.0 |
| calculate.Add.addConstant(Constant, Constant) | 4.0 | 1.0 | 4.0 | 4.0 |
| Total | 226.0 | 165.0 | 233.0 | 272.0 |
| Average | 2.0734 | 1.5138 | 2.138 | 2.495 |
这次代码复杂度普遍较小,因为将较长的类与方法分解成了多个类或者方法。
由于这次使用的递归下降解析方法足够优秀,使得不用大规模重构。每次只有对个别类或者方法的优化解析。
首先,递归下降方法对于正则表达式有着更加优越的可扩展性,对于增加的任何因子都有很好的解决方法。
其次,第二次作业采用的自定义函数调用方法已经很好地解决了嵌套定义的问题。
假如新的一次迭代为加入x的赋值x = C,求算出表达式的值。
扩展十分简单,就是预处理部分,将输入的字符串中的x替换为(C),只是要小心exp中的x。
出现bug的地方为第二次作业,共有两个类型的bug。
exp(Poly),若Poly为因子,则可以少一对括号,但判断因子的方法出现了错误,会将-x判断为因子,输出exp(-x),为错误输出。这两个bug不是设计上的问题,是代码细节上的问题。且这与方法的复杂度没什么必然联系。
x-x,1-1,0-0。我做的优化主要是将冗余的方法或类进行解耦,降低方法复杂度。
这次作业优化的点在于结果的长度,这一方面的优化主要在Unit.toString()中进行优化的。
特殊情况有coe = 0, coe = 1, index = 0, index = 1, exp(0)。
再者当indexOfExp中各项的系数可以提出公因子,长度可以再减少。
这些优化注定会增加代码的复杂度,想办法解耦新增的优化代码,可以减少复杂度的减少。