第三次作业代码量

第一次作业
本次作业需要完成的任务是:读入一个包含加减乘乘方以及括号(最多为一层)的单变量表达式,输出恒等变形展开所有括号后的表达式。整体架构
本次作业是基于递归下降的思想进行处理的。
我的思路是首先进行预处理,删去空白符、连续的加减号、删除前导0,对表达式做初步的简化。然后进行分析和计算。Lexer
在Lexer类里面,我们要完成的工作是分析初步处理之后的表达式的词法。具体实现方法也就是遍历一遍,得到表达式的基本单元并且保存下来以供后续使用,不多赘述。Parser
Parser这个类主要是解析语法,在这个类里面实现了递归下降的方法。具体实现方法是分为ParserExpr, ParserTerm, ParserFactor三个部分,每个方法中调用下一级的方法。到了ParserFactor这里,因为已经到了最底级,所以就在这里返回,依次得到项和表达式。如此表达式就解析完了。
我在设计这一块的时候逻辑不是很清楚,写的比较杂乱。比如处理开头的'-',我在ParserTerm和ParserFactor里面均有涉及,并且解析方法基本一模一样;在处理'^'的时候,我是在ParserTerm里面把这个项依次乘了这么多遍(当然有关于0的特判),但是这种方法可能会导致处理嵌套^的时候爆内存。这些设计思路让我在hw2的时候大改特改,实在是非常痛苦。计算
在本次作业中,因为只会涉及到多项式也就是 a*x^b 这种形式,所以我在Factor接口下的各个类里面定义了一个Hashmap<Integer,BigInteger>类型的属性用来转化成这种形式,便于计算。
在计算的时候,Term类里面实现了因子的乘法,Expr类里面实现了项的加法,当有指数相同的时候系数相加在一起,不相同的话Hashmap就多add一个进去。bug分析
在互测时发现了bug,原因是输出会省略'+'。因为我以为Hashmap遍历的时候会按照指数从0到高这样子遍历,因此导致如果不是常数项开头就会少输出第一个'+'。优化
这一次优化主要是最好开头是个正的项,这样可以减少一个'+'。但是这一点我没做处理。第二次作业
本次作业和第一次相比,多了指数函数和自定义函数,同时支持多层括号嵌套。其中多层括号在第一次作业中实际上已经实现了这一需求,因此这一次作业无需考虑这一部分,重点是指数函数和自定义函数的处理,在这两点上需要大量重构。整体架构
相比第一次,我在Parser类里面对^的处理从ParserTerm移到了方法parserFactor里面,避免内存爆掉的问题。自定义函数处理
新建了两个类Function和FunctionFactor。前者用来记录输入进去的函数表达式,有以下两个属性和两个方法: private static HashMap<String,String> funcmap;
private static HashMap<String, ArrayList<String>> paramap;
public void addFunc(String input)
public static String callFunc(String name, ArrayList<String> actualpara)
FunctionFactor类作为Factor的一个接口,属性和方法如下:private String func;
private Expr expr;
public Expr setExpr()
经过这两个类的处理就得到了函数替换之后的表达式。
在ParserFactor过程中,如果解析到了自定义函数,先解析得到函数的实参,然后通过上面两个类的构造得到一个新的表达式因子返回。指数函数处理
首先建立一个类ExpFactor,expr是"exp()"括号中部分,exp是指数函数整体的次数。public ExpFactor(Expr expr,BigInteger exp) {
this.expr = expr;
this.exp = exp;
}
在Lexer词法分析中,我把exp()作为一个token去分析。在Parser解析的时候,当ParserFactor解析到了"exp()"时就会调用parseExpFactor这个方法。在这个方法中,首先取出来"exp()"括号内的部分,这一部分是一个新的表达式,我们再对这个表达式进行解析,利用解析之后的结果构造一个新的ExpFactor返回。计算
我采用的通项是 a * x^b * exp()的形式,上一次作业的储存方式明显不适用,因此需要一种新的存储方式。
具体的做法是新建了Unit类作为基本单元,Polynomial类用来存储。Unit类存放了系数,x的指数以及指数函数,定义了setCoe,setExp,setPoly,toString等方法。private BigInteger coe
private BigInteger exp
private Polynomial polynomial
Polynomial类存放了构成指数函数的各个Unit基本项,同时实现了addPoly,subPoly,multPoly,toString等方法用于实现计算功能并且最后转化输出。private ArrayList<Unit> units;
bug分析
这次作业新增内容有点多,再加上鼠鼠我写的有点匆忙,我也没仔细考虑,bug很多。