275
社区成员
发帖
与我相关
我的任务
分享先放一张类图

我采用了poly-Mono的核心结构,即将各因子、项、表达式都转化为多项式Poly,而多项式是由一个个的单项式Mono所构成,经过迭代之后,Mono的基本结构为

至于类的设计,我借鉴了OOpre hw7以及上机实验的框架,沿袭了Parser Lexer Expr Term以及诸多Factor类,然后根据归一化思想以及迭代需求,新增了DiyFunc NormalFunc Poly Mono TriFactor DeriveFactor 等类。
我将我所设计的类分为了几个package,处理过程大致如下:
DiyFunc和NormalFunc类进行处理,这是两个静态类,分别用于解析递归函数和普通函数,然后将解析后的函数存储在类自身的静态属性里面,后面可以直接通过类名进行调用,而无需实例化对象toPoly()方法,用于将本类的对象转换为一个多项式
分析结果可知,DiyFunc类、Lexer类和Parser类复杂度较高,为低内聚类。这三个类分别为递归函数类、词法分析类和递归下降执行类,均为程序运行流程的直接体现,因此它们作为低内聚类是可以理解的。同时,其它类耦合度低,可以认为整份代码的抽象化程度还算比较合适。当然,我的DiyFunc类还是比较“笨重”的,因为对于一个参数和两个参数的递归函数,我并没有将其统一起来,而是设计了两个方法,recurrence1和recurrence2,这样的设计无疑是不太好的,但是我刚开始写的时候怕出错,也就分开设计了,后面也没有整改🫠。其实还是有改进空间的。
这里选了复杂度的前几位

其中,Lexer在解析输入时,有非常非常多的分支判断,因此复杂度异常地高,这也是合理的。
然后Mono的toString方法是将单项式转换为字符串,这里面牵扯到三角函数嵌套表达式的诸多问题,因此复杂度也比较高

本人在浏览了一些学长博客和实验代码后,果断选择了递归下降法+Poly-Mono结构,即最后的整个式子是一个多项式Poly,它有若干个单项式Mono相加减组成,在第一次迭代中
$$
Mono = a*x^b
$$
第二次迭代引入了三角函数因子和自定义递归函数这两个新特性,难度可谓是直线上升,思考良久后,我发现,依旧可以将其统一为Poly-Mono结构,只是Mono的结构复杂了一些

private ArrayList<TriFactor> triFactors = new ArrayList<>(),因此,合并同类项时也带来了极大的麻烦,两个单项式可以合并的条件变得异常复杂,需要对应的三角函数的值相等,而怎么判断值相等呢?比如2x^3 * sin(x+1) 和 3x^3 * sin(1+x),那么又需要设置三角函数的类的值相等的判断方法,但三角函数括号里可能是任何表达式或者因子,因此理论上也需要递归下降判断,但是我是直接带调用了toString方法再加上sort方法,判断字符串是否相等,对于大部分简单的情况还是能够拿捏的😁
第三次增加了普通函数和求导因子,普通函数的各种思想和方法在递归函数里已经实现了,问题不大,求导因子的话我是选择在Poly和Mono里求导,这里需要注意的是,Mono求导返回的应该是一个Poly,然后根据乘法法则和链式法则求导即可,还要写一下三角函数的求导。这样设计的好处是只需要在三个类里面写求导方法,而不是每一层结构和每一种因子都要写,比较简洁。
是的,我第一次都有bug,大致就是这样😰

这次迭代直接就爆了
else if (expr.charAt(pos) == '+') {
if (pos > 1 && (expr.charAt(pos - 1) == '^' || expr.charAt(pos - 1) == '*')) {
pos++;
parseNumber(1);
}
else {
tokens.add(new Token(Token.Type.OP, "+"));
pos++;
}
}
else if (expr.charAt(pos) == '-') {
if (pos > 1 && expr.charAt(pos - 1) == '*') {
pos++;
parseNumber(-1);
}
else {
tokens.add(new Token(Token.Type.OP, "-"));
pos++;
}
}
return func.replace(formPara1, "$0").replace(formPara2, "$1")
.replace("$0", "(" + para1 + ")").replace("$1", "(" + para2 + ")");
这里不得不小小吐槽一下:感觉课程组的cost卡的很严,很多的数据其实开销并不算大,但是就是刀不了人,感觉这方面卡的太严了,互测的体验很糟糕,最后不得已交了一些001这样的水数据上去
个人并未做过度的优化,仅仅是在输出时,指数为0,1,系数为0,+-1的特殊情况简化了一下输出,看起来更加舒适,至于过度的卷性能,卷二倍角公式、和差化积公式等,我个人并不感冒,也不觉得有多么高大尚