为什么循环会死?(Collat​​z猜想)

bof*_*edo 5 java math loops collatz

我正在尝试使用java进行一些数学运算,如果它(un)均匀,它会测试一个数字,只要它变为1就可以改变它.

我尝试运行我的循环999999次,它似乎陷入约120000次.好吧,它不是停留在Exception中,只是觉得编译器卡住了.

我对Java不太好,有人可以解释一下这里发生了什么吗?

public static void main(String[] args) {

    int n = 0;
    int highestNumber = 0;
    int highestCounter = 0;
    int counter = 0;
    for (int i = 2;i<1000000;i++) {

        if (i%10000==0) {
            System.out.println(i);
        }
        n = i;
        while (n!=1) {
            if (n%2==0) {   
                n = n/2;
            } else {    
                n=3*n+1;
            }
            counter++;
        }
        if (counter>highestCounter) {

            highestCounter = counter;
            highestNumber = i;
            System.out.println("HIGHEST "+highestNumber+" | counter = "+counter);   
        }
        counter = 0;
        n = 0;
    }
    System.out.println("final "+highestNumber);  
}
Run Code Online (Sandbox Code Playgroud)

isn*_*bad 10

你有一个溢出因为3 * n + 1变大了Integer.MAX_VALUE.因此n得到否定而while循环永远不会停止.

使用long而不是intn!

如果你想检查溢出:

while (n != 1) {
    if (n % 2 == 0) {
        n = n / 2;
    } else {
        if (n > (Integer.MAX_VALUE - 1) / 3) {
            throw new RuntimeException("overflow!");
        }
        n = 3 * n + 1;
    }
    counter++;
}
Run Code Online (Sandbox Code Playgroud)

Java 8的补充

从Java 8开始,Math该类为"精确"算术(加法,减法,乘法,除法)提供了额外的静态方法,以便ArithmeticException在出现溢出时抛出.使用这些方法,代码可以简化:

while (n != 1) {
    if (n % 2 == 0) {
        n = n / 2;
    } else {
        n = Math.addExact(Math.multiplyExact(3, n), 1);
    }
    counter++;
}
Run Code Online (Sandbox Code Playgroud)