301
社区成员
发帖
与我相关
我的任务
分享对一个包含加、减、乘、乘方运算,包含单变量x,含有括号的表达式进行等价化简。
表达式解析:核心思路——找到最后一个运算的运算符,据此二分处理;由于优先级:乘方>乘>[加减],先找最后一个运算的[加减],即最外层括号外、最右边的[加减],然后找最后一个运算的[乘],即最外层括号外、最右边的[乘],以此类推……
表达式处理:除了基本的处理:去除空白符、去除前导零外,有一个特殊的处理——将最外层括号替换为方括号[],方便解析
表达式存储:分两层逻辑结构存储——基本项(Term)和由若干个基本项组成的表达式(Expr);Term存储系数和指数,Expr存储Term的数组Arraylist<Term>
表达式输出:在Term和Expr中都实现toString()方法,Expr.toString()需要下降到Term.toString()输出

| Total Lines | Source Code Lines | Source Code Lines [%] | Comment Lines | Comment Lines [%] | Blank Lines | Blank Lines [%] | |
|---|---|---|---|---|---|---|---|
| Lexer.java | 118 | 85 | 72% | 15 | 13% | 18 | 15% |
| Main.java | 12 | 11 | 92% | 0 | 0% | 1 | 8% |
| Operator.java | 105 | 90 | 86% | 6 | 6% | 9 | 9% |
| Parser.java | 133 | 116 | 87% | 10 | 8% | 7 | 5% |
| Term.java | 57 | 47 | 82% | 1 | 2% | 9 | 16% |
| Total: | 425 | 349 | 82% | 32 | 8% | 44 | 10% |
| Method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| Lexer.Lexer(String) | 0 | 1 | 1 | 1 |
| Lexer.deleteOut(String) | 30 | 9 | 12 | 16 |
| Lexer.getString() | 0 | 1 | 1 | 1 |
| Lexer.preprocess(String) | 3 | 1 | 3 | 4 |
| Lexer.replaceAddsub(String) | 19 | 1 | 6 | 8 |
| Lexer.replaceTop(String) | 10 | 1 | 6 | 6 |
| Main.main(String[]) | 0 | 1 | 1 | 1 |
| Operator.add(ArrayList, ArrayList) | 0 | 1 | 1 | 1 |
| Operator.combine(ArrayList) | 11 | 5 | 7 | 7 |
| Operator.mul(ArrayList, ArrayList) | 6 | 1 | 4 | 4 |
| Operator.parse(String) | 2 | 1 | 2 | 2 |
| Operator.pow(ArrayList, ArrayList) | 2 | 2 | 3 | 3 |
| Operator.sub(ArrayList, ArrayList) | 1 | 1 | 2 | 2 |
| Parser.Parser(String) | 0 | 1 | 1 | 1 |
| Parser.calulate() | 12 | 1 | 5 | 5 |
| Parser.lastAddsub(String) | 13 | 1 | 5 | 8 |
| Parser.lastMul(String) | 8 | 1 | 2 | 6 |
| Parser.lastPow(String) | 8 | 1 | 2 | 6 |
| Parser.toString() | 9 | 3 | 5 | 6 |
| factor.Term.Term(BigInteger, int, BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.addCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.getCoef() | 0 | 1 | 1 | 1 |
| factor.Term.getIndex() | 0 | 1 | 1 | 1 |
| factor.Term.getType() | 0 | 1 | 1 | 1 |
| factor.Term.mulCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.toString() | 14 | 8 | 6 | 9 |
| Total | 148 | 48 | 81 | 103 |
| Average | 5.69 | 1.85 | 3.12 | 3.96 |
| Class | OCavg | OCmax | WMC |
|---|---|---|---|
| Lexer | 5 | 11 | 30 |
| Main | 1 | 1 | 1 |
| Operator | 3 | 6 | 18 |
| Parser | 5.17 | 7 | 31 |
| factor.Term | 2.14 | 9 | 15 |
| Total | 95 | ||
| Average | 3.65 | 6.80 | 19.00 |
新增了自定义函数与指数函数
迭代如下:
主程序新增——读入:建立字符串表,如将f(y,x)=x^2+y^2存储为["f", "yx", "x^2+y^2"]
表达式解析:新增——调用:根据在最外层括号外的逗号识别对应关系,再替换,如f(f(2,2),3)先识别出f,进入括号内,分割成["f(2,2)", "3"],当然分割前最外层括号已经是方括号了,然后替换时,先替换x,再替换y和z,否则会出现错误
表达式解析:新增——parseExp,即识别到e()则进入解析
表达式处理:新增——将"exp"替换成"e",防止自定义函数调用时将exp的x替换掉
表达式存储:新增——Term新增名为expExpr的Expr对象,存储exp()括号里的表达式
表达式输出:新增——Term新增expExprToString()来打印exp()括号里的表达式
表达式解析:改变优先级序列:[fgh、exp]>乘方>……

| Total Lines | Source Code Lines | Source Code Lines [%] | Comment Lines | Comment Lines [%] | Blank Lines | Blank Lines [%] | |
|---|---|---|---|---|---|---|---|
| Add.java | 26 | 22 | 85% | 2 | 8% | 2 | 8% |
| Expr.java | 102 | 84 | 82% | 5 | 5% | 13 | 13% |
| Func.java | 31 | 26 | 84% | 2 | 6% | 3 | 10% |
| Lexer.java | 131 | 101 | 77% | 11 | 8% | 19 | 15% |
| Main.java | 24 | 21 | 88% | 1 | 4% | 2 | 8% |
| Mul.java | 71 | 62 | 87% | 2 | 3% | 7 | 10% |
| Parser.java | 149 | 126 | 85% | 11 | 7% | 12 | 8% |
| Pow.java | 29 | 22 | 76% | 1 | 3% | 6 | 21% |
| Sub.java | 32 | 26 | 81% | 2 | 6% | 4 | 13% |
| Term.java | 269 | 220 | 82% | 11 | 4% | 38 | 14% |
| Total: | 864 | 710 | 82% | 48 | 6% | 106 | 12% |
| Method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| Main.main(String[]) | 1 | 1 | 2 | 2 |
| factor.Expr.Expr() | 0 | 1 | 1 | 1 |
| factor.Expr.Expr(Expr) | 1 | 1 | 2 | 2 |
| factor.Expr.Expr(Term) | 0 | 1 | 1 | 1 |
| factor.Expr.addTerm(Term) | 0 | 1 | 1 | 1 |
| factor.Expr.deleteZeroTerm() | 0 | 1 | 1 | 1 |
| factor.Expr.getTerms() | 0 | 1 | 1 | 1 |
| factor.Expr.isEqual(Expr) | 18 | 9 | 4 | 9 |
| factor.Expr.sortPositive() | 4 | 3 | 3 | 4 |
| factor.Expr.toString() | 8 | 4 | 6 | 7 |
| factor.Term.Term(BigInteger, int, BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.Term(Term) | 2 | 1 | 3 | 3 |
| factor.Term.addCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.addCos(Expr) | 0 | 1 | 1 | 1 |
| factor.Term.addIndex(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.addSin(Expr) | 0 | 1 | 1 | 1 |
| factor.Term.addexpExpr(Expr) | 0 | 1 | 1 | 1 |
| factor.Term.divCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.expExprToString() | 18 | 6 | 7 | 8 |
| factor.Term.getCoef() | 0 | 1 | 1 | 1 |
| factor.Term.getCosList() | 0 | 1 | 1 | 1 |
| factor.Term.getExpExpr() | 0 | 1 | 1 | 1 |
| factor.Term.getIndex() | 0 | 1 | 1 | 1 |
| factor.Term.getSinList() | 0 | 1 | 1 | 1 |
| factor.Term.isEqual(Term) | 5 | 6 | 1 | 6 |
| factor.Term.isEqualCosList(Term) | 19 | 9 | 5 | 10 |
| factor.Term.isEqualSinList(Term) | 19 | 9 | 5 | 10 |
| factor.Term.isMergableTerm(Term) | 4 | 4 | 2 | 5 |
| factor.Term.isNum() | 1 | 1 | 4 | 4 |
| factor.Term.isZeroTerm() | 5 | 5 | 2 | 5 |
| factor.Term.mulCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.powString() | 10 | 7 | 5 | 8 |
| factor.Term.toString() | 18 | 1 | 11 | 15 |
| operator.Add.add(Expr, Expr) | 10 | 6 | 5 | 7 |
| operator.Func.change(String, String, String) | 4 | 1 | 5 | 5 |
| operator.Mul.mul(Expr, Expr) | 5 | 2 | 4 | 5 |
| operator.Mul.mul(Term, Term) | 19 | 9 | 10 | 12 |
| operator.Pow.pow(Expr, Expr) | 3 | 3 | 2 | 4 |
| operator.Sub.sub(Expr, Expr) | 11 | 6 | 6 | 8 |
| parse.Lexer.deleteOut(String) | 30 | 9 | 12 | 16 |
| parse.Lexer.parseFunc(String) | 3 | 1 | 3 | 3 |
| parse.Lexer.preprocess(String) | 3 | 1 | 3 | 4 |
| parse.Lexer.replaceAddsub(String) | 19 | 1 | 6 | 8 |
| parse.Lexer.replaceTop(String) | 11 | 2 | 6 | 7 |
| parse.Parser.finalParse(String) | 7 | 6 | 5 | 8 |
| parse.Parser.lastAddsub(String) | 14 | 1 | 6 | 9 |
| parse.Parser.lastMul(String) | 8 | 1 | 2 | 6 |
| parse.Parser.lastPow(String) | 8 | 1 | 2 | 6 |
| parse.Parser.parseCos(String) | 0 | 1 | 1 | 1 |
| parse.Parser.parseExp(String) | 0 | 1 | 1 | 1 |
| parse.Parser.parseExpr(String) | 18 | 5 | 5 | 5 |
| parse.Parser.parseFunc(String) | 0 | 1 | 1 | 1 |
| parse.Parser.parseSin(String) | 0 | 1 | 1 | 1 |
| Total | 306 | 144 | 166 | 233 |
| Average | 5.77 | 2.72 | 3.13 | 4.40 |
| Class | OCavg | OCmax | WMC |
|---|---|---|---|
| Main | 2 | 2 | 2 |
| factor.Expr | 2.78 | 9 | 25 |
| factor.Term | 3.35 | 11 | 77 |
| operator.Add | 7 | 7 | 7 |
| operator.Func | 5 | 5 | 5 |
| operator.Mul | 7.5 | 11 | 15 |
| operator.Pow | 4 | 4 | 4 |
| operator.Sub | 8 | 8 | 8 |
| parse.Lexer | 6.4 | 11 | 32 |
| parse.Parser | 3.78 | 7 | 34 |
| Total | 209 | ||
| Average | 3.94 | 7.50 | 20.90 |
新增了允许函数嵌套和求导因子
迭代如下:(函数嵌套已经在第二次作业实现,只需对求导因子迭代)
表达式解析:改变优先级序列:[dx、fhg、exp]>乘方……;新增parseDeriv,即识别到d()则进入,返回表达式求导后的结果,因此实现了Expr和Term的deriv方法,由于Term的形式固定,则其求导后的格式固定,很好实现
表达式处理:新增——将"dx"替换成"d"

| Total Lines | Source Code Lines | Source Code Lines [%] | Comment Lines | Comment Lines [%] | Blank Lines | Blank Lines [%] | |
|---|---|---|---|---|---|---|---|
| Add.java | 26 | 22 | 85% | 2 | 8% | 2 | 8% |
| Expr.java | 118 | 98 | 83% | 5 | 4% | 15 | 13% |
| Func.java | 31 | 26 | 84% | 2 | 6% | 3 | 10% |
| Lexer.java | 133 | 102 | 77% | 11 | 8% | 20 | 15% |
| Main.java | 24 | 21 | 88% | 1 | 4% | 2 | 8% |
| Mul.java | 71 | 31 | 44% | 35 | 49% | 5 | 7% |
| Parser.java | 159 | 118 | 74% | 30 | 19% | 11 | 7% |
| Pow.java | 30 | 23 | 77% | 1 | 3% | 6 | 20% |
| Sub.java | 32 | 26 | 81% | 2 | 6% | 4 | 13% |
| Term.java | 330 | 172 | 52% | 127 | 38% | 31 | 9% |
| Total: | 954 | 639 | 67% | 216 | 23% | 99 | 10% |
| Method | CogC | ev(G) | iv(G) | v(G) |
|---|---|---|---|---|
| Main.main(String[]) | 1 | 1 | 2 | 2 |
| factor.Expr.Expr() | 0 | 1 | 1 | 1 |
| factor.Expr.Expr(Expr) | 6 | 1 | 4 | 4 |
| factor.Expr.Expr(Term) | 1 | 1 | 2 | 2 |
| factor.Expr.addTerm(Term) | 1 | 1 | 2 | 2 |
| factor.Expr.deleteZeroTerm() | 0 | 1 | 1 | 1 |
| factor.Expr.deriv() | 2 | 2 | 2 | 3 |
| factor.Expr.getTerms() | 0 | 1 | 1 | 1 |
| factor.Expr.isEqual(Expr) | 18 | 9 | 4 | 9 |
| factor.Expr.sortPositive() | 4 | 3 | 3 | 4 |
| factor.Expr.toString() | 8 | 4 | 6 | 7 |
| factor.Term.Term(BigInteger, int, BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.Term(Term) | 0 | 1 | 1 | 1 |
| factor.Term.addCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.addIndex(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.addexpExpr(Expr) | 0 | 1 | 1 | 1 |
| factor.Term.calBonus(BigInteger) | 5 | 1 | 4 | 5 |
| factor.Term.deriv() | 0 | 1 | 1 | 1 |
| factor.Term.divCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.expExprToString() | 21 | 7 | 7 | 8 |
| factor.Term.getCoef() | 0 | 1 | 1 | 1 |
| factor.Term.getExpExpr() | 0 | 1 | 1 | 1 |
| factor.Term.getIndex() | 0 | 1 | 1 | 1 |
| factor.Term.isEqual(Term) | 3 | 4 | 1 | 4 |
| factor.Term.isMergableTerm(Term) | 2 | 3 | 1 | 3 |
| factor.Term.isNum() | 1 | 1 | 2 | 2 |
| factor.Term.isZeroTerm() | 1 | 2 | 1 | 2 |
| factor.Term.mostBonusFactor() | 8 | 2 | 4 | 6 |
| factor.Term.mulCoef(BigInteger) | 0 | 1 | 1 | 1 |
| factor.Term.powString() | 10 | 7 | 5 | 8 |
| factor.Term.toString() | 6 | 1 | 4 | 5 |
| operator.Add.add(Expr, Expr) | 10 | 6 | 5 | 7 |
| operator.Func.change(String, String, String) | 4 | 1 | 5 | 5 |
| operator.Mul.mul(Expr, Expr) | 5 | 2 | 4 | 5 |
| operator.Mul.mul(Term, Term) | 3 | 3 | 2 | 4 |
| operator.Pow.pow(Expr, Expr) | 3 | 3 | 2 | 4 |
| operator.Sub.sub(Expr, Expr) | 11 | 6 | 6 | 8 |
| parse.Lexer.deleteOut(String) | 30 | 9 | 12 | 16 |
| parse.Lexer.parseFunc(String) | 3 | 1 | 3 | 3 |
| parse.Lexer.preprocess(String) | 3 | 1 | 3 | 4 |
| parse.Lexer.replaceAddsub(String) | 19 | 1 | 6 | 8 |
| parse.Lexer.replaceTop(String) | 11 | 2 | 6 | 7 |
| parse.Parser.finalParse(String) | 6 | 5 | 4 | 7 |
| parse.Parser.lastAddsub(String) | 14 | 1 | 6 | 9 |
| parse.Parser.lastMul(String) | 8 | 1 | 2 | 6 |
| parse.Parser.lastPow(String) | 8 | 1 | 2 | 6 |
| parse.Parser.parseDeriv(String) | 0 | 1 | 1 | 1 |
| parse.Parser.parseExp(String) | 0 | 1 | 1 | 1 |
| parse.Parser.parseExpr(String) | 18 | 5 | 5 | 5 |
| parse.Parser.parseFunc(String) | 0 | 1 | 1 | 1 |
| Total | 254 | 115 | 144 | 197 |
| Average | 5.08 | 2.3 | 2.88 | 3.94 |
| Class | OCavg | OCmax | WMC |
|---|---|---|---|
| Main | 2 | 2 | 2 |
| factor.Expr | 3.2 | 9 | 32 |
| factor.Term | 2.55 | 8 | 51 |
| operator.Add | 7 | 7 | 7 |
| operator.Func | 5 | 5 | 5 |
| operator.Mul | 3.5 | 4 | 7 |
| operator.Pow | 4 | 4 | 4 |
| operator.Sub | 8 | 8 | 8 |
| parse.Lexer | 6.4 | 11 | 32 |
| parse.Parser | 4 | 7 | 32 |
| Total | 180 | ||
| Average | 3.6 | 6.5 | 18 |
缺点:三次作业代码的复杂度都明显高于别人的代码
优点:代码量少,最终作业除去注释只有639行;UML图简洁
我采用的“根据最后运算的运算符分割”的二分法,能很好应对表达式的解析问题,所以没有进行重构;如果加入三角函数,就增加基本项Term的存储形式即可,如 HashMap<Expr, BigInteger> sinList
没有公测和被互测的bug
能省略的0和1都省略了,方法是特判系数、指数是否是0或1,据此输出
exp部分实现提公因数时,比较不同公因数的长度影响,方法根据cxc的想法实现,枚举 i (2 <= i <= 9),若 i 整除最大公因数 gcd,则比较提取公因数 (gcd / i) 的长度影响
不懂如何实现exp的“分裂”优化,如
exp((1-2576816*x^4-25768160*x^7-96630600*x^10-161051000*x^13-100656875*x^16))^4
的非常好形式是
exp((-625*x^16-1000*x^13-600*x^10-160*x^7-16*x^4))^644204*exp(4)
使我性能分得到21分