分析C ++ rand()

时间:2014-12-20 13:10:24

标签: c++ random cryptography

我正在尝试预测由 C ++ rand() 函数生成的数字。这是代码的链接,它可能使用:click

这是我的代码,模拟 rand()

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {
        srand(time(0));
        unsigned a = rand();
        unsigned b = rand();
        cout << (a * 1103515245U + 12345U) % 0x7fffffffU << '\n';
        cout << b << '\n'; // they should match, right? But they don't...
        return 0;
}

为什么我的值不匹配 b

2 个答案:

答案 0 :(得分:4)

如果选择TYPE_0生成器,glibc仅使用旧的线性同余生成器,如您在链接的代码中所示。 (默认情况下,它使用TYPE_3 generator。)如果RNG缓冲区大8字节,这是唯一的情况。您可以使用initstate强制旧行为:

char state[8];
initstate(time(0), state, 8);

unsigned a = rand();
unsigned b = rand();
cout << (a * 1103515245u + 12345u) % 0x7fffffffu << '\n';

然后你经常得到相同的数字,当你不这样做时,它只会被一个数字抵消。粗略地看,我没有能够准确地确定为什么会出现这种差异(可能会在稍后编辑),但我怀疑是带有一些恶作剧。

编辑:好的,我明白了。 glibc的rand在内部使用带符号的算术,它使用&而不是%作为模数。如果(a * 1103515245 + 12345)变为负数,则会产生一位差异。如果你写

int a = rand();
int b = rand();

cout << (a * 1103515245 + 12345) & 0x7fffffff << '\n';

然后你会一直得到相同的结果。好吧,真正的ab应该是int32_t以获得最大的便携性,但我怀疑这不是一个问题。因为无论如何,库内部和可移植性是一种失败的原因。

答案 1 :(得分:0)

添加到Wintermute的回复:默认情况下,它使用TYPE_3 generator