陷入无限循环?(也许)
Stuck in an infinite loop? (Maybe)
我正试图用c++完成Project Euler Problem 14,但我确实被卡住了。现在,当我运行这个问题时,它被困在"迄今为止":计数最高的数字:113370,计数为155到目前为止:计数最高的数字,但当我尝试将I值更改为113371以上时,它会起作用。发生了什么事??
问题是:
下面的迭代序列是为正整数:n→n/2(n为偶数)n→3n+1(n为奇数)
使用上面的规则,从13开始,我们生成以下内容序列:
13→40→20→10→5.→16→8.→4.→2.→1可以看出序列(从13开始,到1结束)包含10个项。虽然它还没有被证明(Collatz问题),但它是以为所有的起始数字都以1结束。哪个起始号码,低于一百万,生产最长的链条?
#include<stdio.h>
int main() {
int limit = 1000000;
int highNum, number, i;
int highCount = 0;
int count = 0;
for( number = 13; number <= 1000000; number++ )
{
i = number;
while( i != 1 ) {
if (( i % 2 ) != 0 ) {
i = ( i * 3 ) + 1;
count++;
}
else {
count++;
i /= 2;
}
}
count++;
printf( "So Far: the number with the highest count: %d with the count of %dn",
number, count );
if( highCount < count ) {
highCount = count;
highNum = number;
}
count = 0;
//break;
}
printf( "The number with the highest count: %d with the count of %dn",
highNum, highCount );
}
您得到的是整数溢出。像这样更新你的代码并亲自查看:
if (( i % 2 ) != 0 ) {
int prevI = i;
i = ( i * 3 ) + 1;
if (i < prevI) {
printf("oops, i < prevI: %dn", i);
return 0;
}
count++;
}
您应该将i
的类型更改为long long
或unsigned long long
以防止溢出。
(是的,缓存中间结果)
记住所有中间结果(直到某个适当的高数字)
此外,使用一个足够大的类型:
#include <stdio.h>
static int collatz[4000000];
unsigned long long collatzmax;
int comp(unsigned long long i) {
if(i>=sizeof collatz/sizeof*collatz) {
if(i>collatzmax)
collatzmax = i;
return 1 + comp(i&1 ? 3*i+1 : i/2);
}
if(!collatz[i])
collatz[i] = 1 + comp(i&1 ? 3*i+1 : i/2);
return collatz[i];
}
int main() {
collatz[1] = 1;
int highNumber= 1, highCount = 1, c;
for(int i = 2; i < 1000000; i++)
if((c = comp(i)) > highCount) {
highCount = c;
highNumber = i;
}
printf( "The number with the highest count: %d with the count of %dn",
highNumber, highCount );
printf( "Highest intermediary number: %llun", collatzmax);
}
关于coliru:http://coliru.stacked-crooked.com/a/773bd8c5f4e7d5a9
运行时间较小的变体:http://coliru.stacked-crooked.com/a/2132cb74e4605d5f
The number with the highest count: 837799 with the count of 525
Highest intermediary number: 56991483520
BTW:遇到的最高中介需要36位来表示为无符号数字。
使用您的算法,您可以计算几个时间相同的序列。您可以缓存以前数字的结果并重用它们。
类似于:
void compute(std::map<std::uint64_t, int>& counts, std::uint64_t i)
{
std::vector<std::uint64_t> series;
while (counts[i] == 0) {
series.push_back(i);
if ((i % 2) != 0) {
i = (i * 3) + 1;
} else {
i /= 2;
}
}
int count = counts[i];
for (auto it = series.rbegin(); it != series.rend(); ++it)
{
counts[*it] = ++count;
}
}
int main()
{
const std::uint64_t limit = 1000000;
std::map<std::uint64_t, int> counts;
counts[1] = 1;
for (std::size_t i = 2; i != limit; ++i) {
compute(counts, i);
}
auto it = std::max_element(counts.begin(), counts.end(),
[](const std::pair<std::uint64_t, int>& lhs, const std::pair<std::uint64_t, int>& rhs)
{
return lhs.second < rhs.second;
});
std::cout << it->first << ":" << it->second << std::endl;
std::cout << limit-1 << ":" << counts[limit-1] << std::endl;
}
演示(10秒)
不要一次又一次地重新计算相同的中间结果!
给定
typedef std::uint64_t num; // largest reliable built-in unsigned integer type
num collatz(num x)
{
return (x & 1) ? (3*x + 1) : (x/2);
}
那么collatz(x)
的值只取决于x
,而不取决于您何时调用它。(换句话说,collatz
是一个纯函数。)因此,您可以为x
的不同值存储collatz(x)
的值。为此,可以使用std::map<num, num>
或std::unordered_map<num, num>
。
以下是完整的解决方案,供参考。
这是在科利鲁,计时(2.6秒)。
- 过载'operator new'如何导致无限循环?
- C++正则表达式无限循环
- 程序在尝试猜测它选择的随机数时进入无限循环?
- 遍历链表时的无限循环
- 循环链表:无限循环
- 比较两个字符串后卡在无限循环中
- 在做一段时间内检查字符的无限循环
- 逐字读取文本文件中的每一行并转换为 int(无限循环或崩溃?
- 在这个无限循环中,当输入 0 时终止,当输入 int 范围之外的任何内容时,程序行为不正常
- 可能的无限循环
- 超出 int 的值范围后的无限循环
- 为什么这段代码会导致无限循环?
- 运行无限循环的最小二叉树问题
- 在分配和发布递增循环迭代器时C++无限循环(gcc 错误?
- 连接线程时的无限循环
- 为什么这种方法会进入无限循环?
- 由于QTextStream的无限循环
- Qt 在另一个线程中无限循环
- 陷入无限循环?(也许)
- 我知道该去哪里看,也许这是一个无限循环?(C++,使用VS2012)