我正在尝试预测由 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 ?
答案 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';
然后你会一直得到相同的结果。好吧,真正的a
和b
应该是int32_t
以获得最大的便携性,但我怀疑这不是一个问题。因为无论如何,库内部和可移植性是一种失败的原因。
答案 1 :(得分:0)
添加到Wintermute的回复:默认情况下,它使用TYPE_3 generator。