3

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

创建一个int(value) 并为其分配一个值。

如果 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;
    }
}

}

4

5 回答 5

7

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

于 2012-09-04T20:26:20.607 回答
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该类,它适用于任何数字。

于 2012-09-04T20:34:48.387 回答
2

因为你的整数溢出了。改用“long”,您的代码将运行良好,至少在您的序列甚至超过 longs 范围之前。

于 2012-09-04T20:27:04.370 回答
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();
    }

}

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

于 2012-09-04T20:34:03.667 回答
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:");
    }
}
于 2012-09-04T20:42:46.627 回答