欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

解一元一次方程的那些坑(记洛谷P1022题RE的经历)

程序员文章站 2022-04-07 09:04:30
...

important!!!

遇到RE不可怕,纯粹的RE还行(后面没有WA的话,可能你的算法本身没错)。
这固然会使得我们困惑,但我们只需要记得最常见的几种RE,加以分析,给一些脑洞大的测试样例就一般可以测出隐藏的语法Bug。。。

空指针还好吧,在OJ里的大问题不是空指针,一般是NumberFormatException或者越界的异常等等………………自己去测测,必有惊喜,必有福报~~

终于做了一个黄题,Nice!!!

题目要求

P1022题目链接

解一元一次方程的那些坑(记洛谷P1022题RE的经历)
解一元一次方程的那些坑(记洛谷P1022题RE的经历)

分析

其实就是拿过来一个一元一次方程然后求解。。。

问题是,坑是真多。。下面分享几个。。。。

  • 首先是你得处理符号,因为比如说“-”即是减号也是负号,“+”只代表加号(我们不会在正数前面加+)。
  • 接下来你要注意怎么去split到数据,如果你不想逐个处理,可以分治,先按照“=”切分为左右两部分字符串,然后左右分别按照“+”或者“-”切分。(正则为"[+]|[-]"
  • 然后你得注意开头的符号要消去,不要直接split导致出现"",这是糟糕的情况,会RE。(比如“-2x+2=3”)
  • 还有就是你得知道:-0.0000000000001这样的数在截出来以后是-0.000,这不能被OJ接收。。。
  • 接着上面一条说,另外非常恶心的是,-0.0/2得到的是-0.000(保留三位小数),这个-0.000其实按照我们补码理论是不存在的,它的存在就很恶心,在jshell里测试的时候就是与0.000相等的(包括与0相等)。其实一样,但你放OJ里就gg了,是不行的。。。
  • ……

第一次提交——WA+RE

这个WA的比较弱智,因为没注意输出格式。。。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String expression = scanner.nextLine();
        scanner.close();
        //未知变量的表示(小写字母)
        char x = 'x';
        for (char c : expression.toCharArray()) {
            if (c >= 'a' && c <= 'z') {
                x = c;
                break;
            }
        }
        String[] expressionArr = expression.split("=");
        boolean leftNeg = false, rightNeg = false;
        String left = expressionArr[0], right = expressionArr[1];
        if (left.startsWith("-")) {
            leftNeg = true;
            left = left.substring(1, left.length());
        }
        if (right.startsWith("-")) {
            rightNeg = true;
            right = right.substring(1, right.length());
        }
        Queue<Character> leftCharacters = new LinkedList<>();
        if (leftNeg) {
            leftCharacters.offer('-');
        } else {
            leftCharacters.offer('+');
        }
        for(char c : left.toCharArray()) {
            if (c == '+' || c == '-') {
                leftCharacters.offer(c);
            }
        }
        Queue<Character> rightCharacters = new LinkedList<>();
        if (rightNeg) {
            rightCharacters.offer('-');
        } else {
            rightCharacters.offer('+');
        }
        for(char c : right.toCharArray()) {
            if (c == '+' || c == '-') {
                rightCharacters.offer(c);
            }
        }
        String[] leftArr = left.split("[+]|[-]"), rightArr = right.split("[+]|[-]");
        int leftCounter = 0, leftCoefficient = 0, rightCounter = 0, rightCoefficient = 0;
        outer:
        for (String leftObj : leftArr) {
            char[] chars = leftObj.toCharArray();
            char sign = leftCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    leftObj = leftObj.substring(0, leftObj.length()-1);
                    leftCoefficient += Integer.parseInt(sign+leftObj);
                    continue outer;
                }
            }
            //不是未知量
            leftCounter += Integer.parseInt(sign+leftObj);
        }
        outer:
        for (String rightObj : rightArr) {
            char[] chars = rightObj.toCharArray();
            char sign = rightCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    rightObj = rightObj.substring(0, rightObj.length()-1);
                    rightCoefficient += Integer.parseInt(sign+rightObj);
                    continue outer;
                }
            }
            //不是未知量
            rightCounter += Integer.parseInt(sign+rightObj);
        }
        System.out.printf("%.3f", ((double)(rightCounter-leftCounter))/(leftCoefficient-rightCoefficient));
    }
}

解一元一次方程的那些坑(记洛谷P1022题RE的经历)

第二次提交——RE

第二次RE了,平时测试没问题,但就很不解。。。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String expression = scanner.nextLine();
        scanner.close();
        //未知变量的表示(小写字母)
        char x = 'x';
        for (char c : expression.toCharArray()) {
            if (c >= 'a' && c <= 'z') {
                x = c;
                break;
            }
        }
        String[] expressionArr = expression.split("=");
        boolean leftNeg = false, rightNeg = false;
        String left = expressionArr[0], right = expressionArr[1];
        if (left.startsWith("-")) {
            leftNeg = true;
            left = left.substring(1, left.length());
        }
        if (right.startsWith("-")) {
            rightNeg = true;
            right = right.substring(1, right.length());
        }
        Queue<Character> leftCharacters = new LinkedList<>();
        if (leftNeg) {
            leftCharacters.offer('-');
        } else {
            leftCharacters.offer('+');
        }
        for(char c : left.toCharArray()) {
            if (c == '+' || c == '-') {
                leftCharacters.offer(c);
            }
        }
        Queue<Character> rightCharacters = new LinkedList<>();
        if (rightNeg) {
            rightCharacters.offer('-');
        } else {
            rightCharacters.offer('+');
        }
        for(char c : right.toCharArray()) {
            if (c == '+' || c == '-') {
                rightCharacters.offer(c);
            }
        }
        String[] leftArr = left.split("[+]|[-]"), rightArr = right.split("[+]|[-]");
        int leftCounter = 0, leftCoefficient = 0, rightCounter = 0, rightCoefficient = 0;
        outer:
        for (String leftObj : leftArr) {
            char[] chars = leftObj.toCharArray();
            char sign = leftCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    leftObj = leftObj.substring(0, leftObj.length()-1);
                    leftCoefficient += Integer.parseInt(sign+leftObj);
                    continue outer;
                }
            }
            //不是未知量
            leftCounter += Integer.parseInt(sign+leftObj);
        }
        outer:
        for (String rightObj : rightArr) {
            char[] chars = rightObj.toCharArray();
            char sign = rightCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    rightObj = rightObj.substring(0, rightObj.length()-1);
                    rightCoefficient += Integer.parseInt(sign+rightObj);
                    continue outer;
                }
            }
            //不是未知量
            rightCounter += Integer.parseInt(sign+rightObj);
        }
        System.out.print(x + "=");
        System.out.printf("%.3f", ((double)(rightCounter-leftCounter))/(leftCoefficient-rightCoefficient));
    }
}

解一元一次方程的那些坑(记洛谷P1022题RE的经历)

自检过程

其实试了很多,都没问题,于是就开一个大数,,,

先是尝试了大数,被爆了NumberFormatException,如我所料,题没限制范围,就改为long保保险。。

但还是这样:所以就意识到一个巨大的思维差别:我们写的一元一次方程一般+x这样就OK,但我们的程序只能直接认识+1x,这就得我们再分出一种情况讨论。。。
解一元一次方程的那些坑(记洛谷P1022题RE的经历)

然后继续,还是异常RE:
解一元一次方程的那些坑(记洛谷P1022题RE的经历)

就是分析部分分析到的-0.000的问题,我们应该让它输出0.000,这就要求必须在上面操作。

偏偏这个数不是0.000(因为这是截出来的,我们在上面judge的是原数,所以是大于-0.0005而不能变成-0.001的数值,是负数,所以处理一下就OK)

第三次提交——RE(好一些了,就剩一个RE了)

这次纯属智障行为,因为左边改了,右边没改,这点一定要注意!!!

不要犯这种无脑错。。。

代码不放了,显得智障。。。

解一元一次方程的那些坑(记洛谷P1022题RE的经历)

第四次提交——AC

写的比较冗长,不是很好。。也没抽出来函数,直接main到底、。。。。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String expression = scanner.nextLine();
        scanner.close();
        //未知变量的表示(小写字母)
        char x = 'x';
        for (char c : expression.toCharArray()) {
            if (c >= 'a' && c <= 'z') {
                x = c;
                break;
            }
        }
        String[] expressionArr = expression.split("=");
        boolean leftNeg = false, rightNeg = false;
        String left = expressionArr[0], right = expressionArr[1];
        if (left.startsWith("-")) {
            leftNeg = true;
            left = left.substring(1, left.length());
        }
        if (right.startsWith("-")) {
            rightNeg = true;
            right = right.substring(1, right.length());
        }
        Queue<Character> leftCharacters = new LinkedList<>();
        if (leftNeg) {
            leftCharacters.offer('-');
        } else {
            leftCharacters.offer('+');
        }
        for(char c : left.toCharArray()) {
            if (c == '+' || c == '-') {
                leftCharacters.offer(c);
            }
        }
        Queue<Character> rightCharacters = new LinkedList<>();
        if (rightNeg) {
            rightCharacters.offer('-');
        } else {
            rightCharacters.offer('+');
        }
        for(char c : right.toCharArray()) {
            if (c == '+' || c == '-') {
                rightCharacters.offer(c);
            }
        }
        String[] leftArr = left.split("[+]|[-]"), rightArr = right.split("[+]|[-]");
        long leftCounter = 0, leftCoefficient = 0, rightCounter = 0, rightCoefficient = 0;
        outer:
        for (String leftObj : leftArr) {
            char[] chars = leftObj.toCharArray();
            char sign = leftCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    leftObj = leftObj.substring(0, leftObj.length()-1);
                    if ("".equals(leftObj)) {
                        leftCoefficient++;
                    } else {
                        leftCoefficient += Long.parseLong(sign+leftObj);
                    }
                    continue outer;
                }
            }
            //不是未知量
            leftCounter += Long.parseLong(sign+leftObj);
        }
        outer:
        for (String rightObj : rightArr) {
            char[] chars = rightObj.toCharArray();
            char sign = rightCharacters.poll();
            for (char c : chars) {
                if (c == x) {
                    rightObj = rightObj.substring(0, rightObj.length()-1);
                    if ("".equals(rightObj)) {
                        rightCoefficient++;
                    } else {
                        rightCoefficient += Long.parseLong(sign+rightObj);
                    }
                    continue outer;
                }
            }
            //不是未知量
            rightCounter += Long.parseLong(sign+rightObj);
        }
        double result = ((double)(rightCounter-leftCounter))/(leftCoefficient-rightCoefficient);
        if (result > -0.0005 && result < 0) {
            System.out.printf("%c=%.3f", x, 0.000);
        } else {
            System.out.printf("%c=%.3f", x, result);
        }
    }
}

庆祝一下:
解一元一次方程的那些坑(记洛谷P1022题RE的经历)

相关标签: # 菜鸡逛洛谷