5

我正在尝试用java进行一些数学运算,如果它(不)偶数,它会测试一个数字,只要它达到1就改变它。

我尝试运行我的循环 999999 次,它似乎卡在大约 120000 次左右。好吧,它并没有因异常而停止,只是感觉编译器卡住了。

我对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);  
}
4

5 回答 5

10

你有一个溢出,因为3 * n + 1变得大于Integer.MAX_VALUE. 所以n变成负数,while 循环永远不会停止。

使用long而不是intfor n

如果您想检查是否溢出:

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++;
}

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++;
}
于 2013-09-27T14:15:36.903 回答
4

你有溢出问题。像这样更改代码,您会看到它:

    while (n!=1) {
        if(n < 0) throw new IllegalStateException("n should not become < 0" + n + "-" + counter);
        if(n > ((Integer.MAX_VALUE -1) / 3)) System.out.println("n too large. " + n);
        if (n%2==0) {   
            n = n/2;
        } else {    
            n=3*n+1;
        }
        counter++;
    }

如果你做nlong工作正常。

于 2013-09-27T14:15:02.930 回答
1

嗯,你的代码对我来说看起来不错。你正在解决一个非常典型的问题

n 是整数吗?如果它很短,你可能会溢出它。

除此之外,整数的最大值超过 20 亿,所以你不应该打它。以防万一,尝试将 n 设置为 long 以查看是否有帮助

编辑:例如,数字 77671 根据我阅读的博客(阅读:未经测试),i = 77671 的最高 n 是 1,047,216,490

所以我认为 n 应该很长,现在我想多了

于 2013-09-27T14:13:57.140 回答
1

此更正有效:

public static void main(String []args){
    long highestCounter = -1;
    long highestNumber = -1;
    for (long i = 2;i<1000000;i++) {

        if (i%1000==0) {
            System.out.println(i);
        }
        long n = i;
        long counter = 0;
        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); 
}
于 2013-09-27T14:17:02.980 回答
0

您只需在 while 块内运行一个无限循环,然后添加System.out.println(counter);counter++查看发生了什么..

于 2013-09-27T14:22:37.390 回答