BUAA_OO_第一单元作业
心得
第一单元的作业让我体会到了面向对象的威力,在pre2中已经知道了面向对象这一种数据组织形式。最让我有感觉的就是这次作业中表达式作为一个因子的这种设置,这种设置让类的定义有了递归的关系。
除此之外,我还感受到了模块化编程对于字符串处理的用处,Lexer实际上提供了一个标准化识别字符串序列的方法,它的返回值的形式由我们在程序中写死,我们就可以在Parse中对返回的值进行标准化的解析。这样大大减少了我们字符串解析工作和我们主控代码的耦合度。
框架介绍
第一次作业定下了我三次作业的框架,有一个MainClass函数作为主控,之后有三个工具类,分别是Parser,Lexer和Print。Parser函数对字符串进行解析并且存储为我们想要的形式,Parser函数解析的对象是Lexer对象。Print函数则是为了化简输出而使用。
而真正要面向的对象是Expr,Term类和一个相对固定的类Calc。为什么这么说,因为Calc就是一个终点,无论打印还是化简还是解析,他都是终点,而Expr类和Term类则不是,他们都有自己的成员。
倘若我们规范地按照给出的形式化描述的思路去设计架构,那么我们会发现,自己不由自主地就完成了一个难点,就是递归定义,由于是刚刚接触java语言,我对于java中类的掌握还不是很纯熟,一开始对于这种Expr作为因子的情况颇为头疼,但是当自己定义出了类的框架在书写时,就不由自主地将Term类的上一级Expr类作为了Term类的成员来使用,也慢慢更加理解了java允许类的递归调用这一设计的深意。
这里是本次作业的性能分析
method | CogC | ev(G) | iv(G) | |
---|---|---|---|---|
expr.Calc.Calc(BigInteger, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Calc.mult(Calc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Calc.print(Print) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.addTerm(Term) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.addTo(Expr) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.calc() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.Expr() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.mult(Expr) | 3.0 | 1.0 | 3.0 | 3.0 |
expr.Expr.print(Print) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Print.add(BigInteger, BigInteger) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.Print.Print() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Print.print() | 44.0 | 1.0 | 18.0 | 18.0 |
expr.Term.addFactor(Factor) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.addTo(Term) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.calc() | 6.0 | 1.0 | 4.0 | 4.0 |
expr.Term.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.print(Print) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.Term() | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.Lexer(String) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.next() | 12.0 | 4.0 | 6.0 | 13.0 |
main.Lexer.operatorNext() | 12.0 | 4.0 | 6.0 | 13.0 |
main.Lexer.peek() | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.powerNext() | 13.0 | 4.0 | 7.0 | 14.0 |
main.MainClass.main(String[]) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Parser.parseExpr() | 8.0 | 1.0 | 7.0 | 7.0 |
main.Parser.parseFactor() | 22.0 | 4.0 | 8.0 | 8.0 |
main.Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Parser.parseTerm(BigInteger) | 3.0 | 1.0 | 4.0 | 4.0 |
Total | 130.0 | 43.0 | 91.0 | 112.0 |
Average | 4.193548387096774 | 1.3870967741935485 | 2.935483870967742 |
介绍:
ev(G) 基本复杂度是用来衡量程序非结构化程度的,非结构成分降低了程序的质量,增加了代码的维护难度,使程序难于理解。因此,基本复杂度高意味着非结构化程度高,难以模块化和维护。实际上,消除了一个错误有时会引起其他的错误。
iv(G) 模块设计复杂度是用来衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。模块设计复杂度是从模块流程图中移去那些不包含调用子模块的判定和循环结构后得出的圈复杂度,因此模块设计复杂度不能大于圈复杂度,通常是远小于圈复杂度。
v(G) 是用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,经验表明,程序的可能错误和高的圈复杂度有着很大关系。
可以看到,各个next方法,读取下一个字符的方法、解析方法和打印方法的复杂度是比较高的,这很正常。
优缺点
自己代码结构的优点就是完成了这个任务,而缺点就是在解析字符串时,当我碰到了括号后边有指数时,我便使用了mult方法,将它与自身乘几次之后再放入,导致解析部分和化简部分有了一定程度的耦合,见下图。其实之后优化时书写了simplify方法,并为Expr类加上了index,在这个方法里面直接化简就好了。
bug
bug是在互测阶段被找到的,我对于/t的理解有问题,所以处理不了这种字符,将空白字符全部替换之后就好了。
hack
我在所有作业中都没有hack别人成功,所以这方面就不介绍经验了。
第二次作业
心得
其实最大的心得是自定义函数带给我的,引用老师ppt中的一句话,自定义函数其实就是字符串的变换,但是变换不等于有简单的替换,我们会遇到很多问题。首先,Lexer函数中对字符串的解析规则是相对固定的,我们简单替换后的字符串还能不能满足它的要求;其次,我们的替换究竟能不能得到我们想象中的字符串,会不会出现误替换。
这些问题是可以通过细心来解决的,但是我的细心程度确实差那么一点,出现了一个因为字符串替换而导致的bug。
框架
优点:最大程度地利用第一次作业剩余的架构。但是,新的类有了之后(新的运算有的可能会好一点),要改的东西注定是不少的。比如三角函数这一个类,不优化则已,优化就一定要重写equals和hashcode方法,这个推荐使用官方重写的方法,之后再去做修改,自己写可能会有超出认知范围的bug。
缺点:缺点也是一目了然,为了避免加入解析时的替换,我使用了在原先编程中一般都可以大大简化问题的方法,先进行一遍预解析替换字符串,再开始真正的解析。这样确实是简化了,但是不值得,因为进行精确的字符串替换需要的精力是巨大的。
bug:
第一个自己重写的hashcode方法爆了int
第二个字符串替换终究还是出锅了,自己对于sin,cos括号里内容默认就是常量和变量,但是替换的时候加上了括号,无法解析。比如
1
f(x) = sin(x)
f(-111111)
我的字符串会替换为sin((-111111)),我的程序认为应该是sin(-111111),所以无法解析。
第三个自己优化的时候忘记判断输出一个零的情况了
自己出bug的这几个点感觉都不是因为代码结构太过于复杂,主要是因为最后优化完成的时间比较赶导致没有充足的时间进行几遍检查。
最后附上第二次作业的性能分析
CogC | ev(G) | iv(G) | v(G) | |
---|---|---|---|---|
expr.Expr.addTerm(Term) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.addTo(Expr) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.calc() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.Expr() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.mult(Expr) | 3.0 | 1.0 | 3.0 | 3.0 |
expr.Expr.print() | 14.0 | 5.0 | 9.0 | 10.0 |
expr.Expr.resimplify(ArrayList) | 11.0 | 1.0 | 7.0 | 7.0 |
expr.Expr.setIndex(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.addvar(String) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.Function(String) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.NormalCalc.firstprint(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.mult(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.NormalCalc(BigInteger, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.print(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.trigprint() | 4.0 | 1.0 | 3.0 | 3.0 |
expr.Term.addFactor(Factor) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.addTo(Term) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.calc() | 7.0 | 1.0 | 4.0 | 4.0 |
expr.Term.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.print() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.Term() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.add(TrigCalc) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.copy(TermPrint) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.TermPrint.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashmapifEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.match(TermPrint) | 22.0 | 11.0 | 8.0 | 13.0 |
expr.TermPrint.mult(Factor) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.print(int) | 8.0 | 2.0 | 5.0 | 6.0 |
expr.TermPrint.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.TermPrint(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.TrigCalc.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.isIfSin() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.print() | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TrigCalc.TrigCalc(BigInteger, NormalCalc, boolean) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.Lexer(String) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.next() | 11.0 | 2.0 | 8.0 | 17.0 |
main.Lexer.operatorNext() | 11.0 | 2.0 | 8.0 | 17.0 |
main.Lexer.peek() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.deSum(String) | 13.0 | 1.0 | 7.0 | 8.0 |
main.MainClass.getFunctions() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.main(String[]) | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.mainread() | 16.0 | 1.0 | 6.0 | 7.0 |
main.Parser.parseExpr() | 8.0 | 1.0 | 7.0 | 7.0 |
main.Parser.parseFactor() | 24.0 | 5.0 | 12.0 | 13.0 |
main.Parser.parseFunction(int) | 9.0 | 1.0 | 7.0 | 7.0 |
main.Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Parser.parseTerm(BigInteger) | 3.0 | 1.0 | 4.0 | 4.0 |
main.Parser.parseTrig() | 17.0 | 6.0 | 8.0 | 10.0 |
Total | 244.0 | 91.0 | 191.0 | 224.0 |
Average | 3.935483870967742 | 1.467741935483871 | 3.0806451612903225 |
我们看到为了优化而设计的match方法的复杂度非常高,这也告诉我们优化其实是有着很大风险的。
第三次作业
心得
这一次吸收了上一次的教训,痛下决心学习了deepClone方法,实现了深克隆。这不仅仅帮助我解决了自定义函数替换的问题,也在后面化简的时候让提取公因式成为可行。这一次和同学进行了交流,开始使用IDEA自己补充的hashcode和equals方法的自行改变来完成要求。并且应代码风格检查要求,将一些组件及时拆出增强了代码的复用,方便了修改。
框架
本次首先应深克隆的要求,对代码架构进行了一次调整,主要是在自变量解析部分实现了替换功能,之后又对专门实现优化的类TermPrint进行了一部分功能的优化。
1、实现了深克隆,替换非常方便,而且比较准确
2、优化与原代码完全分离,可以方便的定位是不是优化的错误
bug:
本次强测与互测都没有发现bug,但也没有hack别人成功
最后附上代码分析
CogC | ev(G) | iv(G) | v(G) | |
---|---|---|---|---|
expr.Expr.deepClone() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.equals(Object) | 6.0 | 6.0 | 2.0 | 6.0 |
expr.Expr.Expr() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.mult(Expr) | 3.0 | 1.0 | 3.0 | 3.0 |
expr.Expr.print() | 7.0 | 5.0 | 5.0 | 6.0 |
expr.Expr.printType() | 8.0 | 5.0 | 8.0 | 9.0 |
expr.Expr.replace(Expr[]) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.resimplify(ArrayList) | 20.0 | 6.0 | 7.0 | 10.0 |
expr.Expr.setIndex(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.setsign(BigInteger) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.simplify() | 5.0 | 1.0 | 4.0 | 4.0 |
expr.Function.Function(Expr, int) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.equals(Object) | 3.0 | 3.0 | 2.0 | 4.0 |
expr.NormalCalc.firstprint(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.mult(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.NormalCalc(BigInteger, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.print(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.trigprint(TermPrint) | 19.0 | 1.0 | 14.0 | 14.0 |
expr.Term.addFactor(Factor) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.addTo(Term) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.calc() | 10.0 | 1.0 | 5.0 | 5.0 |
expr.Term.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.replace(Expr[]) | 6.0 | 1.0 | 5.0 | 5.0 |
expr.Term.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.simplify() | 5.0 | 1.0 | 4.0 | 4.0 |
expr.Term.Term() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.add(TrigCalc) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.copy() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.equals(Object) | 6.0 | 6.0 | 2.0 | 6.0 |
expr.TermPrint.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.getNormalCalc() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.getTrigCalcHashMap() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashmapifEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashmapifOne() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.match(TermPrint) | 17.0 | 5.0 | 10.0 | 11.0 |
expr.TermPrint.matchJudge(ArrayList, ArrayList, TermPrint, TermPrint) | 33.0 | 11.0 | 14.0 | 17.0 |
expr.TermPrint.matchMerge(TermPrint, TrigCalc) | 4.0 | 3.0 | 4.0 | 4.0 |
expr.TermPrint.print(int) | 6.0 | 2.0 | 4.0 | 5.0 |
expr.TermPrint.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.setTrigCalcs(ArrayList) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.TermPrint(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.trigCalcsifEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.deepClone() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.TrigCalc.equals(Object) | 3.0 | 3.0 | 3.0 | 5.0 |
expr.TrigCalc.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.isIfSin() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.matchs(Object) | 3.0 | 3.0 | 2.0 | 4.0 |
expr.TrigCalc.print() | 5.0 | 1.0 | 5.0 | 5.0 |
expr.TrigCalc.setContent(Expr) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.setIfSin(boolean) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.setIndex(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.simplify() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.TrigCalc(BigInteger, Expr, boolean) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Var.getNumber() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Var.Var(int) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.Lexer(String) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.next() | 13.0 | 2.0 | 11.0 | 19.0 |
main.Lexer.operatorNext() | 13.0 | 2.0 | 11.0 | 19.0 |
main.Lexer.peek() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.deSum(String) | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.getFunctions() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.main(String[]) | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.mainread() | 13.0 | 1.0 | 5.0 | 6.0 |
main.Parser.parseExpr() | 8.0 | 1.0 | 7.0 | 7.0 |
main.Parser.parseFactor() | 18.0 | 8.0 | 12.0 | 13.0 |
main.Parser.parseFunction(int) | 1.0 | 1.0 | 2.0 | 2.0 |
main.Parser.parseNormal() | 5.0 | 1.0 | 3.0 | 3.0 |
main.Parser.parsePow(Expr) | 4.0 | 1.0 | 3.0 | 3.0 |
main.Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Parser.parseSum() | 1.0 | 1.0 | 2.0 | 2.0 |
main.Parser.parseTerm(BigInteger) | 3.0 | 1.0 | 4.0 | 4.0 |
main.Parser.parseTrig(String) | 2.0 | 2.0 | 1.0 | 2.0 |
Total | 306.0 | 142.0 | 257.0 | 300.0 |
Average | 3.558139534883721 | 1.6511627906976745 | 2.988372093023256 |
对比第二次作业里的优化大match方法,将match方法拆解为三部分之后,各个部分的复杂度都相对较低,可以看到,善用函数完成不同的功能有利于bug率的下降。
优化
最后来系统的谈一下优化,基础的优化就是合并同类项,HashMap基本就是无可避免的需要使用,而且判断两项可以合并也是个麻烦事,建议先使用一定的方法(比如为运算结果建一个专门的类)将每一个项进行标准化之后再进行化简。
还有一些细枝末节的,比如sin(0), cos(0), x*x, 第一个优先输出正号的项,这些细节但很重要,建议优先完成这一些,可怜我费大力气做了三角函数优化但是没有做这种优化,性能分就不大可观。
最后谈一谈三角函数的化简这个有两个我只实现了第一个,就是平方和为一,这个看似容易,但是实现很难,性价比比较低,一个标准的首先一定要能提取公因式,之后化简的时候会产生新类型(除了系数以外的其他部分),自己的化简遍历要能够支持新类型的假如,我是使用了一个二重循环,之后用ArrayList存储数据,每次把数据存到ArrayList末尾,遍历过程中ArrayList会有所更新,但不影响正确性。可以考虑两个项为(公因式)乘常数+-(公因式)乘sin(x)^2或者cos(x)^2以及(公因式)乘sin(x)^2+-(公因式)乘cos(x)^2这两种形式。
第二个就是二倍角了,这个我粗略地想了一下2乘cos(x)^2-1应该可以在上面的化简中实现,sin(x)乘cos(x)可能就需要单独遍历寻找,不过实现难度不是很大。
总而言之,自己的优化策略还是有很多问题的,第一次作业细节没有到位,导致没有拿到全分,第二次过于注重优化,导致对正确性检查不足,第三次选择了性价比最低的优化,可以说败在了优化这里。
总结
expr.Expr.addTerm(Term) | 0.0 | 1.0 | 1.0 | 1.0 |
---|---|---|---|---|
expr.Expr.addTo(Expr) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.calc() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Expr.Expr() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.mult(Expr) | 3.0 | 1.0 | 3.0 | 3.0 |
expr.Expr.print() | 14.0 | 5.0 | 9.0 | 10.0 |
expr.Expr.resimplify(ArrayList) | 11.0 | 1.0 | 7.0 | 7.0 |
expr.Expr.setIndex(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Expr.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.addvar(String) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.Function(String) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.getCnt() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Function.getVars() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.NormalCalc.firstprint(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.mult(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.NormalCalc(BigInteger, BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.print(TermPrint) | 23.0 | 1.0 | 15.0 | 15.0 |
expr.NormalCalc.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.NormalCalc.trigprint() | 4.0 | 1.0 | 3.0 | 3.0 |
expr.Term.addFactor(Factor) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.addTo(Term) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.calc() | 7.0 | 1.0 | 4.0 | 4.0 |
expr.Term.getSign() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.print() | 1.0 | 1.0 | 2.0 | 2.0 |
expr.Term.setSign(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.Term.Term() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.add(TrigCalc) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.copy(TermPrint) | 1.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.TermPrint.getNum() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.hashmapifEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.match(TermPrint) | 22.0 | 11.0 | 8.0 | 13.0 |
expr.TermPrint.mult(Factor) | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TermPrint.print(int) | 8.0 | 2.0 | 5.0 | 6.0 |
expr.TermPrint.setNum(BigInteger) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TermPrint.TermPrint(NormalCalc) | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.equals(Object) | 2.0 | 2.0 | 2.0 | 3.0 |
expr.TrigCalc.getContent() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.getIndex() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.isIfSin() | 0.0 | 1.0 | 1.0 | 1.0 |
expr.TrigCalc.print() | 2.0 | 1.0 | 2.0 | 2.0 |
expr.TrigCalc.TrigCalc(BigInteger, NormalCalc, boolean) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.Lexer(String) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Lexer.next() | 11.0 | 2.0 | 8.0 | 17.0 |
main.Lexer.operatorNext() | 11.0 | 2.0 | 8.0 | 17.0 |
main.Lexer.peek() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.deSum(String) | 13.0 | 1.0 | 7.0 | 8.0 |
main.MainClass.getFunctions() | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.main(String[]) | 0.0 | 1.0 | 1.0 | 1.0 |
main.MainClass.mainread() | 16.0 | 1.0 | 6.0 | 7.0 |
main.Parser.parseExpr() | 8.0 | 1.0 | 7.0 | 7.0 |
main.Parser.parseFactor() | 24.0 | 5.0 | 12.0 | 13.0 |
main.Parser.parseFunction(int) | 9.0 | 1.0 | 7.0 | 7.0 |
main.Parser.Parser(Lexer) | 0.0 | 1.0 | 1.0 | 1.0 |
main.Parser.parseTerm(BigInteger) | 3.0 | 1.0 | 4.0 | 4.0 |
main.Parser.parseTrig() | 17.0 | 6.0 | 8.0 | 10.0 |
Total | 244.0 | 93.0 | 193.0 | 226.0 |
Average | 3.8125 | 1.453125 | 3.015625 |
bug: