为什么这个Ruby代码比同等的C ++代码快得多?

时间:2013-05-08 19:26:00

标签: c++ math

最近我一直在经历一些简单的项目Euler问题并用Ruby和C ++解决它们。但对于关于Collat​​z猜想的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。

3 个答案:

答案 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。