【问题标题】:Analyzing C++ rand()分析 C++ rand()
【发布时间】:2014-12-20 13:10:23
【问题描述】:

我正在尝试预测 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

【问题讨论】:

  • 您为什么希望它们匹配?你从哪里得到这个奇怪的预测公式? rand() 应该产生随机值。
  • 其实它是伪随机的......如果你看它的来源,你会发现下一个数字取决于上一个
  • 您确定您的编译器完全使用您链接到的代码吗?工具链是您自己构建的吗?
  • 我的工具链其实是我自己搭建的,版本有点不同,但也有类似的行
  • @jpo38:上面的代码尝试预测序列中的下一个数字,假设rand() 实现特别差。

标签: c++ random cryptography


【解决方案1】:

如果选择了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 在内部使用有符号算术,并且它使用&amp; 而不是% 作为模数。如果(a * 1103515245 + 12345) 变为负数,这会产生一位差异。如果你写

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

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

那么你总是得到相同的结果。好吧,真的ab 应该是int32_t 以获得最大的可移植性,但我怀疑这不是问题。因为库的内部结构和可移植性无论如何都是一种失败的原因。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这会更好作为对他的回应的评论
    • 我不知道如何在评论中添加超链接
    猜你喜欢
    • 2019-01-30
    • 2012-11-08
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多