当它们不应该使用整数和双精度时给出不同的答案

时间:2013-06-20 22:43:21

标签: java math integer double iteration

我正在使用java解决Project Euler Problem 14。我不是要求帮助解决问题。我已经解决了,但我碰到了一些我无法弄清楚的东西。

问题是这样的:

  

为正集合定义以下迭代序列   整数:

     

n = n / 2,如果n是偶数   n = 3n + 1,如果n是奇数

     

使用上面的规则并从13开始,我们生成以下内容   序列:

     

13 - > 40 - > 20 - > 10 - > 5 - > 16 - > 8 - > 4 - > 2 - >这里,链的长度是10个数字。

     

查找产生最长链的1,000,000以下的起始编号。

所以我写了这段代码:

public class Euler014 {
    public static void main(String[] args){
        int maxChainCount = 0;
        int answer = 0;
        int n;
        int chainCount = 1;

        for(int i = 0; i < 1000000; i++){
            n = i;
            while(n > 1){
                if(n%2 == 0){       //check if even
                    n /= 2;
                }else{              //else: odd
                    n = 3*n + 1;
                }
                chainCount++;
            }
            if(chainCount > maxChainCount){ //check if it's the longest chain so far
                maxChainCount = chainCount;
                answer = i;
            }
            chainCount = 1;
        }       
        System.out.println("\n\nLongest chain: i = " + answer);     
    }
}

这给了我答案910107,这是错误的。

但是,如果我将我的n变量的类型更改为double n它会运行并给出答案837799,这是正确的!

这让我很困惑,因为我看不出有什么区别。我理解,如果我们使用int并进行分割,我们最终可能会在我们不打算时舍入数字。但在这种情况下,我们总是检查n是否可以除以2,然后除以2.所以我认为使用整数是完全安全的。我没看到什么?

这是完整的代码,复制,粘贴并运行它,如果你想亲眼看看。尽管迭代很多,它仍会在几秒钟内运行。 =)

1 个答案:

答案 0 :(得分:10)

你的问题是溢出的。如果您将int n更改为long n,您将得到正确答案。

请记住:序列中的数字可以是 非常大 。如此之大,他们超出了int的范围。但不是(在这种情况下)doublelong的。

在链中的某一点,n827,370,449并且您遵循3n + 1分支。该值希望为2,482,111,348,但它会溢出int(正区域为2,147,483,647)的容量,并将您带到-1,812,855,948。事情从那里向南走。 : - )

所以你的理论是你可以用整数(我应该说整数)数字是正确的。但他们必须具备完成任务的能力。