我正在使用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.所以我认为使用整数是完全安全的。我没看到什么?
这是完整的代码,复制,粘贴并运行它,如果你想亲眼看看。尽管迭代很多,它仍会在几秒钟内运行。 =)
答案 0 :(得分:10)
你的问题是溢出的。如果您将int n
更改为long n
,您将得到正确答案。
请记住:序列中的数字可以是 非常大 。如此之大,他们超出了int
的范围。但不是(在这种情况下)double
或long
的。
在链中的某一点,n
为827,370,449
并且您遵循3n + 1
分支。该值希望为2,482,111,348
,但它会溢出int
(正区域为2,147,483,647
)的容量,并将您带到-1,812,855,948
。事情从那里向南走。 : - )
所以你的理论是你可以用整数(我应该说整数)数字是正确的。但他们必须具备完成任务的能力。