OO Unit1 博客作业

__shiina 2024-03-30 21:03:56

OO第一单元博客作业


UML图与架构分析

​ 第一单元的主要任务是完成表达式的解析和化简,本单元最终完成的作业的UML图如下:

img

​ 本任务先才采用递归下降法对表达式的结构进行建模,然后再利用建模出的结构进行计算。主要对于不同层级的表达式(Expr)、项(Item)、因子(Factor)分别建立对象,值得一提的是因子(Factor)层级有很多子类:表达式因子(ExprFactor)、指数函数因子(ExpFactor)、常数因子(ConstFactor)、求导因子(DerivativeFactor)和PowFactor(幂函数因子),本任务中分别将其抽象成了对应的对象。这里的对象只负责接受递归下降语法分析器的分析建立相应的层次结构,计算的时候调用cal()方法得到每个部分化简后的结果,结果统一采用多项式(UnitList)的形式,其是单个单项式(Unit)的加和。

​ 每个单项式表示:
$$
coef * x^{xpower}*e^{epower}
$$
​ 其中coef是BigInteger, xpower是long, epwoer为多项式(UnitList)

​ 这样虽然能够表示出每个层次的计算化简结果,但是也导致了Unit和UnitList耦合度较高

​ 为了方便计算化简,本任务还实现了Unit和UnitList的常用方法如求导、相加、判断是否为同类项等

​ 其中判断是否为同类型并没有很严格的完成,只采用了判断toString是否相等这种简单粗暴的办法,其实忽略了很多情况,例如1+x和x+1会被判断为不是同类型,存在很大的改进空间,如果想改进可以重写Unit和UnitList和Unit的equals()和hashCode()方法,或者在UnitList中改采用HashMap来存储Unit。

​ 本任务采用预处理字符串替换的方式来处理自定义函数,涉及到的细节很多。比如exp中的x会和变量的x混淆,因此预处理将exp替换为E,对于f(x) = 2 + x , 2*f(x)来说,直接替换变成 2 * 2+x 会出现计算优先级的问题,因此在替换完成后的整体需要加括号,同样的原因对于替换的参数也应该加括号。

代码复杂度分析

​ 本任务的代码长度分析如下:

img

​ 比较复杂的是实现自定义函数提花你的Function类和实现计算的Unit类和UnitList类,值得改进的是本次作业的注释太少了,平时还是应该养成写注释的习惯。

ConstFactor.cal()0.01.01.01.0
ConstFactor.ConstFactor(BigInteger)0.01.01.01.0
ConstFactor.toString()0.01.01.01.0
DerivativeFactor.cal()0.01.01.01.0
DerivativeFactor.DerivativeFactor()0.01.01.01.0
DerivativeFactor.DerivativeFactor(Expr)0.01.01.01.0
DerivativeFactor.toString()0.01.01.01.0
ExpFactor.cal()1.01.02.02.0
ExpFactor.ExpFactor(Factor, int)0.01.01.01.0
ExpFactor.toString()1.02.02.02.0
Expr.addItem(Item)0.01.01.01.0
Expr.cal()2.01.03.03.0
Expr.neg()0.01.01.01.0
Expr.toString()1.01.02.02.0
ExprFactor.cal()1.01.02.02.0
ExprFactor.ExprFactor()0.01.01.01.0
ExprFactor.ExprFactor(Expr, int)0.01.01.01.0
ExprFactor.toString()1.02.02.02.0
Factor.cal()0.01.01.01.0
Function.addFunction(char, String, String)0.01.01.01.0
Function.addFunction(String)1.02.01.02.0
Function.Function()0.01.01.01.0
Function.replace(String)1.01.02.02.0
Function.replaceFunction(String, char, String, String)36.01.010.012.0
Item.addFactor(Factor)0.01.01.01.0
Item.cal()5.01.04.04.0
Item.neg()0.01.01.01.0
Item.toString()1.01.02.02.0
Lexer.Lexer()0.01.01.01.0
Lexer.Lexer(String)0.01.01.01.0
Lexer.nextExpr()13.01.08.010.0
Lexer.nextFactor()18.012.06.012.0
Lexer.nextItem()7.01.06.07.0
Main.main(String[])31.01.016.018.0
PowFactor.cal()0.01.01.01.0
PowFactor.PowFactor()0.01.01.01.0
PowFactor.PowFactor(int)0.01.01.01.0
PowFactor.toString()1.02.01.02.0
Unit.add(Unit, Unit)0.01.01.01.0
Unit.derivate(Unit)4.02.03.04.0
Unit.isPositive()0.01.01.01.0
Unit.isSimilar(Unit, Unit)1.02.01.02.0
Unit.isZero()0.01.01.01.0
Unit.mul(int)0.01.01.01.0
Unit.mul(Unit, Unit)0.01.01.01.0
Unit.neg()0.01.01.01.0
Unit.toString()5.01.04.04.0
Unit.Unit()0.01.01.01.0
Unit.Unit(BigInteger)0.01.01.01.0
Unit.Unit(int)0.01.01.01.0
Unit.Unit(UnitList)0.01.01.01.0
UnitList.add(Unit)10.04.06.07.0
UnitList.add(UnitList, UnitList)1.01.02.02.0
UnitList.clone()0.01.01.01.0
UnitList.derivate(UnitList)1.01.02.02.0
UnitList.isEmpty()0.01.01.01.0
UnitList.isEqual(UnitList, UnitList)3.03.02.04.0
UnitList.isZero()3.03.02.03.0
UnitList.mul(int)1.01.02.02.0
UnitList.mul(UnitList, UnitList)3.01.03.03.0
UnitList.neg()1.01.02.02.0
UnitList.toString()7.04.03.05.0
UnitList.UnitList()0.01.01.01.0
UnitList.UnitList(Unit)0.01.01.01.0
Total161.091.0137.0160.0
Average2.5156251.4218752.1406252.5

虽然总体圈复杂度不算特别高。但还是可以看出圈复杂度最高的部分在于词法分析器对表达式层次的解析和字符串替换的过程,这两个过程本身逻辑就比较复杂,if和循环也比较多,主要是很多都重复地实现了括号匹配的,根据研讨课上某位同学分享的可以为括号匹配专门编写一个实现类感觉是一个可以有效降低圈复杂度的思路。

Bug

在本次任务中主要遇到了如下几个bug

  1. 错误优化表达式括号

    例如Exp(2+x),其中2+x只能作为表达式因子,括号不可去,应该输出Exp((2+x))

  2. 指数采用int存储溢出

    没有正确的分析数据范围,因为存在括号嵌套从而可能导致指数非常大,应该采用BigInteger存储

  3. 符号处理不正确

    在处理项前面的符号的时候忘了index++,从而导致符号没有正确被处理

    优化分享

    在本次任务中合并同类项的优化做得不太完全,但还做了一些其他简单的小优化

    1. 为了保证Exp中表达式有正确的括号,本任务暴力的将所有表达式都加了括号,但正则查找了形如Exp((+-number))的去除了括号,降低了长度

    2. 为了减少长度,在表达式中优先输出正数,如将-3+x改为x-3,长度降低了1

    心得体会

    本次OO单元作业完成情况不太理想,最开始搞错了ddl的时间没及时提交,第三次作业的bug修复过程也忘记了提交,希望能合理安排时间,认真及时完成之后的每次oo作业。

    在单元作业的编写中,发现了在每个类内部加一个main方法就可以独立的测试每个类,这个可以比较方便快捷的实现对类的测试,在多次debug中也明白了单元测试的重要性,如果代码写完了才来一起测试就算找出问题也很难确定bug的位置,就算确定了bug的位置也很难调试。同时在编写程序的过程中我也明白了设计的重要性,最开始设计字符串替换的时候考虑得不够全面,漏掉了很多特殊情况,从而导致最后一而

...全文
84 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文围绕基于NSGA-2算法的电-热-气综合需求响应(IDR)在综合能源系统中的多目标优化问题展开研究,提出了一种融合智能优化算法与能源系统协同调度的解决方案。研究系统性地构建了包含电力、热力与天然气多能耦合的综合能源系统模型,设计了以能效提升、运行成本降低和环境效益优化为目标的多目标优化框架,并采用NSGA-2算法求解该复杂非线性优化问题,获得Pareto最优解集。文中详细阐述了IDR机制建模方法、多目标优化问题的数学建模过程以及NSGA-2算法的关键实现步骤,包括编码方式、交叉变异策略与非支配排序机制,并通过Matlab代码实现了完整的仿真验证流程,展示了该方法在平衡多个冲突目标方面的优越性能。; 适合人群:具备电力系统、能源系统建模或优化算法基础的研究生、科研人员及工程技术人员,特别适用于从事综合能源系统规划、需求响应策略设计、多目标进化算法应用等相关领域的研究人员; 使用场景及目标:①应用于综合能源系统的运行优化与规划决策,支持多能互补场景下的协同调度分析;②为科研工作者提供NSGA-2算法在能源系统中实际应用的完整Matlab代码实现范例,助力学术论文复现、算法改进与模型拓展; 阅读建议:建议读者结合文中提供的Matlab代码,按照系统建模、目标函数设计、约束处理到算法实现的研究脉络逐步学习,重点关注Pareto前沿的生成过程、多目标权衡分析及算法参数敏感性,以深入掌握多目标进化算法在复杂能源系统优化中的工程化应用方法。

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧