导语:

本次的总结,我打算这么写:UML图、回忆、收获。虽然想的很好,但是因为老夫连挂了后两次作业,尤其是第三次写的和狗啃的一样。所以第三次的内容,我可能重点会主要放在读别人的代码上,毕竟没吃过猪肉,但还是可以见见猪跑的。

正文:

第一次作业:

 

具体思路,就是先将输入的字符串进行一定程度的处理(比如:去掉空格、合并正负号),然后通过正则表达式:"([+-])((\\d+)\\*)?x(\\*{2}([+-]?\\d+))?"
对字符串的各个项进行判断,进行处理。具体代码如下:

static final String polyRegex =
        "([+-])((\\d+)\\*)?x(\\*{2}([+-]?\\d+))?";

public String parseStr(String inputStr) {
    String string = this.processStr(inputStr);
    Pattern pattern = Pattern.compile(polyRegex);
    Matcher matcher = pattern.matcher(string);
    while (matcher.find()) {
        String operatorStr = matcher.group(1);
        String coefStr = matcher.group(3);
        String indexStr = matcher.group(5);

       
BigInteger coef;
        BigInteger index;
        if (operatorStr.equals("+")) {
            //coef = Integer.getInteger(coefStr);
           
if (null == coefStr) {
                coef = new BigInteger("1");
            }
            else {
                //coef = Integer.getInteger(coefStr);
                //coef = Integer.valueOf(coefStr);
               
coef = new BigInteger(coefStr);
            }
        }
        else {
            if (null == coefStr) {
                //coef = -1;
               
coef = new BigInteger("-1");
            }
            else {
                //coef = - Integer.getInteger(coefStr);
                //coef = - Integer.valueOf(coefStr);
               
coef = new BigInteger(coefStr).negate();
            }
        }

        if (null == indexStr) {
            //index = 1;
           
index = new BigInteger("1");
        }
        else {
            //index = Integer.getInteger(indexStr);
            //index = Integer.valueOf(indexStr);
           
index = new BigInteger(indexStr);
        }

        //poly.addTerm(coef, index);
       
HashMap<BigInteger, BigInteger> map = poly.getTerms();
        if (map.containsKey(index)) {
            BigInteger originalCoef = map.get(index);
            //map.put(index, coef + originalCoef);
           
map.put(index, coef.add(originalCoef));
        }
        else {
            map.put(index, coef);
        }
    }

   
return string;
}

可以看得出parseStr()写的很凌乱,这个方法做的功能设定的时候不清晰,换句话说层次设计的不好。
首先,指数、系数干的话罗列在一起,很乱;而且指数的判断严格和系数的判断挂钩,耦合严重。导致我在进行课下测试的时候,很多bug都和这里有关。
其次,我们可以很容易看得出来,在抽离指数、系数过程中,过多的if、else语句来判断特殊格式的问题,导致逻辑结构混乱,混乱就容易出bug。
应当怎样解决呢,我这里的想法进攻抛砖引玉。可以设计一个这样的方法standardizeStr()对输入的字符串进行标准化,将每一项都变成标准的:
[符号](系数)*x**[符号](指数)
通过标准化,可以极大地减少指数、系数特殊判断的问题。

这也是我在第二次作业中实现的思路。

第二次作业:

 

与上一次作业相比,这一次增加了一个TerneryIndex类,即三元指数,但是本质上和上一次没有区别。

首先标准化,将每一项都化为如下的形式:

a*x**b*sin(x)**c*cos(x)**d

这一步涉及了合并因子指数,最终分别提取x\sin(x)\cos(x)的指数作为三元指数对,以此作为上一次作业中hashmap的键值。作为上一次的迭代,从而重用之前的代码。

我们来看看这个方法怎么样。从我个人的角度出发,现在想想,这种做法其实蠢得可以。最致命的问题就是没有迭代空间。如果将来指导书出了tan(x),根据这个思路,我们还得给标准项加上tan(x),然后正则表达式的捕获组也需要进行修改,hashmap的键也要改,然后输出的时候要考虑的特殊情况更多、更复杂(写完第二次作业,我就觉得下一次作业必然要重构)。

其次就是性能堪忧,因为自己给自己找活干,做了大量不必要的工作,当然现阶段只是多了sin(x), cos(x)的工作,还能跑起来,但是这不是一个可以继续迭代的方案。

 

说完TerneryIndex,我们来看看判断WRONG FORMAT!的问题。代码如下:

static final String constant = "([+-]?\\d+)";
static final String index = "(\\*{2}" + constant + ")";
static final String trigonometric = "(((sin)|(cos))\\(x\\)" + "(" + index + ")?)";
static final String power = "(x" + "(" + index + ")?)";
static final String factor = "(" + constant + "|" + power + "|" + trigonometric + ")";
static final String term = "([+-]?" + factor + "(\\*" + factor + ")*)";
static final String inputForm = "^([+-]?)" + term + "(([+-]" + term + ")*)$";
public boolean inputFormJudge(String inputStr) {
    if (null == inputStr) {
        return false;
    }
    String string = inputStr.replaceAll("[ \t]", "");
    Pattern pattern = Pattern.compile(inputForm);
    Matcher matcher = pattern.matcher(string);

    return matcher.find();
}

好嘛,用一个大正则来判断输入的对不对,会有什么问题?

首先,极其非常特别容易栈溢出。这一次控制了输入量,所以侥幸没有栈溢出。

其次,加了这一步,个人认为这是在浪费性能。纵观整个程序,我们用正则遍历了输入的字符串两次,一次判断、一次处理。

所以我个人提出的解决方法是这样的:

每一个因子进行判断、并处理,然后在原字符串中删掉该因子。处理完了,判断处理后的原字符串是否为空字符串,是就return true,否则就输出WF,然后return false。

posted on 2020-03-21 18:28  BuniQ  阅读(185)  评论(0编辑  收藏  举报