为什么java程序冻结在113882上?

A P*_*ikh 1 java freeze collatz

我编写了一个java程序,使用collat​​z序列查找数字链的长度.collat​​z序列为:如果数字是偶数,则将其除以2,如果是奇数,则乘以3并加1.当数字达到1时序列结束.Clatz序列的附加信息.我的程序发现数字的链长从1到1百万,但它停在113382.没有显示错误信息,程序只是停止打印数字.

*编辑:我测试了它,结果是当程序在113383时,链收敛到负值.有谁能解释一下?

我已经包含了完整的代码,因为它很短.

public static void main(String[] args) {
    int max =0, maxChain=0;
    for(int i = 2; i <1000000; i++ )
    {
        int c =i;
        int counter = 0;
        while(c != 1)
        {
            if(c%2 ==0) c/=2;
            else c= 3*c+1;
            counter++;
        }
        if(counter > maxChain)
        {
            maxChain =counter;
            max = i;
        }
        System.out.println(i);
    }
    System.out.println(max +" has a chain length of " +maxChain);

}
Run Code Online (Sandbox Code Playgroud)

Boh*_*ian 6

对于数字113383,迭代#120产生827370449.下一次迭代在数值上产生的2482111348数据太大而无法容纳int变量,因此它会导致算术溢出回绕到负数.

从那里开始,所有迭代都会产生负数,虽然结果重复循环,但结果-1的循环终止条件1永远不会发生,因此会产生无限循环.

但是,如果将变量类型更改为long,则可以避免溢出(无论如何都是此起始编号),并且序列在247次迭代后完成.


顺便说一句,我通过简单地打印每次迭代发现了这一点,并且它立即变得明显发生了什么.你可以做同样的事情并自己解决这个问题.调试就像编码一样方便,因为我们都会遇到令我们感到惊讶的编码情况,并找到自己总是更令人满意和令人难忘的原因(所以你不会再陷入同样的​​陷阱).