最近我一直在经历一些简单的项目Euler问题并用Ruby和C ++解决它们。但对于关于Collatz猜想的Problem 14,我的C ++代码在我终止它之前大约持续了半个小时,但是当我将代码翻译成Ruby时,它在9秒内就解决了。
这种差异对我来说是难以置信的 - 我一直认为C ++几乎总是比Ruby快,特别是对于数学过程。
我的代码如下。
C ++:
#include <iostream>
using namespace std;
int main ()
{
int a = 2;
int b = 2;
int c = 0;
while (b < 1000000)
{
a = b;
int d = 2;
while (a != 4)
{
if (a % 2 == 0)
a /= 2;
else
a = 3*a + 1;
d++;
}
if (d > c)
{
cout << b << ' ' << d << endl;
c=d;
}
b++;
}
cout << c;
return 0;
}
运行时间 - 老实说我不知道,但这真的很长时间。
和Ruby:
#!/usr/bin/ruby -w
a = 0
b = 2
c = 0
while b < 1000000
a = b;
d = 2
while a != 4
if a % 2 == 0
a /= 2
else
a = 3*a + 1
end
d+=1
end
if d > c
p b,d
c=d
end
b+=1
end
p c
运行时间 - 大约9秒。
知道这里发生了什么吗?
P.S。 C ++代码比Ruby代码运行得更快,直到它达到100,000。
答案 0 :(得分:33)
你溢出int
,所以它没有终止。在c ++代码中使用int64_t
代替int
。
您可能需要为此包含stdint.h
..
答案 1 :(得分:3)
在您的情况下,问题是C ++实现中的错误(数字溢出)。
但是请注意,在某些记忆中交易可以比你正在做的更快地得到结果......
提示:假设您发现从231开始,您需要127个步骤来结束计算,并假设从另一个数字开始,您在22个步骤后得到231 ...您还需要执行多少步骤?
答案 2 :(得分:3)
使用32位算术,C ++代码在a = 3*a + 1
上溢出。使用带符号的32位算法,问题变得复杂,因为a /= 2
行将保留符号位。
这使得a
更难以等于4,实际上当b
达到113383时,a
溢出并且循环永远不会结束。
使用64位算术时没有溢出,因为当a
为704511时,b
最大值为56991483520。
不看数学,我推测无符号32位算术“可能”有效,因为乘法和无符号除法都将以2 ^ 32为模。并且考虑到程序的运行时间短,值不会覆盖64位频谱的太多,所以如果一个值等于4模2 ^ 32,它“可能”实际上等于4。