是什么导致Java(冰雹序列)在我的程序中崩溃

时间:2012-09-04 20:20:05

标签: java math integer sequence

我制作了一个程序来执行(通常称为)hailstone序列,该程序基本上是这样做的:

创建int(值)并为其赋值。

如果int是偶数,则除以2。

如果int是奇数,则将其乘以3并加1。继续此过程,直到n等于1。

它似乎与大多数数字一样正常,但这个数字99888769,应用程序挂起一个负整数。这是为什么?他们说没有人能够证明它停止了,我没想到我已经解决了这个问题。但知道为什么我的应用程序停止会很有趣。 -

    private void hailStoneSequence(){
    int value = 99888769;
    int i = 0;
    boolean trueOrFalse = isOddOrEven (value);
    while (value != 1){
        while (trueOrFalse == true && value != 1){
            i++;
            int previousValue = value;
            value = value / 2;
            println( previousValue +" is even, so I take half: "+value);
            trueOrFalse = isOddOrEven (value); // returning true or false, and inserting the newly divided number. So that it breaks loop when nescesary.
        }
            while (trueOrFalse == false && value != 1){
                i++;
                int previousValue = value;
                value = (value * 3) + 1;
                println (previousValue +" is odd, so I make 3n+1: "+value); 
                trueOrFalse = isOddOrEven (value);  
            }
                }       
    println ("\n\nThe process took "+i+" to reach "+value);
}

private boolean isOddOrEven(int value){
    /*
     * Takes an value and returns true, if that number is even.
     * Else it returns false.
     */
    if (value % 2 != 0){
    return false;
    }else{
        return true;
    }
}

}

5 个答案:

答案 0 :(得分:7)

当你不断增加int时,它们最终会(看起来像一个令人吃惊的行为)变成负数,因为你超过了int类型的最大值(2 ^ 31-1),即你最终改变用于存储数字符号的位(int的二进制表示)。请改用long

答案 1 :(得分:3)

你实际上选了一个有趣的起始号码。从那里开始,你最终得到的数字是:768879215。将它乘以3并加1超过了int可以存储的最大值(2 ^ 31-1),因此它“溢出”为负数。对于负数,冰雹序列并不总是收敛到1,事实上在这种情况下它会永远重复以下序列:

-122
-61
-182
-91
-272
-136
-68
-34
-17
-50
-25
-74
-37
-110
-55
-164
-82
-41
-122

您可以使用long替代,您的代码最多可以使用(2 ^ 63-1),或者使用BigInteger类,它适用于任何数字。

答案 2 :(得分:2)

因为整数溢出。改为使用“long”,代码运行正常,至少在序列超出longs范围之前。

答案 3 :(得分:2)

你的逻辑对我来说似乎很复杂。重新编写代码以使其更清晰,您应该能够看到发生了什么:

public class HailStoneSequence {

    public void sequence() {
        int value = 99888769;
        int i = 0;
        while (value != 1) {
            int previousValue = value;
            if (value % 2 == 0) {
                value = value / 2;
                System.out.println(previousValue + " is even, so I take half: " + value);
            } else {
                value = (value * 3) + 1;
                System.out.println(previousValue + " is odd, so I make 3n+1: " + value);
            }
        }

        i++;
        System.out.println("\n\nThe process took " + i + " to reach " + value);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HailStoneSequence instance = new HailStoneSequence();
        instance.sequence();
    }

}

现在,如果你运行它,你应该看到它不会停止,但它会重复。因此,它产生了一个无限的系列....

答案 4 :(得分:1)

您的初始种子值会导致您达到“int”数据类型的整数溢出。这导致重复的负值序列。您可以更改为使用“长”数据类型,也可以使用不同(较小)的种子值开始。

public class HailStoneSequence 
{

    public static void processSequence()
    {
        long value = 99888769;   // works due to larger type range
        // int value = 99888769; // causes negative repeating sequence
        // int value = 81;       // works with smaller seed
        int i=0;

        while(value != 1)
        {
            System.out.println("The value is:" + value);
            i++;
            if(value % 2 == 0)
            {
                value /= 2;
            }
            else
            {
                value = value * 3 + 1;
            }
        }
        System.out.println("The process took " + i + " iterations to solve.");
    }

    public static void main(String[] args) 
    {
        System.out.println("Begin Hailstorm:");
        HailStoneSequence.processSequence();
        System.out.println("End Hailstorm:");
    }
}