rand()有时会连续返回吗?

Goh*_*han 31 c c++ random visual-c++

我只是好奇,单线程程序可以连续两次调用获得相同的返回值rand()吗?

那么,这个断言会不会发生?

assert(rand() != rand());
Run Code Online (Sandbox Code Playgroud)

nos*_*nos 46

如果我们能找到一个例子,你问题的答案就是"是".

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  unsigned int i;
  for(i = 0; ; i++) {
    int r = rand();
    if (r == rand()) {
        printf("Oops. rand() = %d; i = %d\n", r, i);
        break;
    }
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Oops. rand() = 3482; i = 32187使用Visual Studio 2010在Windows上打印.

编辑:使用下面的版本检测2连续rand()调用返回相同值的所有序列.C仅指定rand()应返回"0到RAND_MAX范围内的伪随机整数",RAND_MAX应至少为32767.对PRNG的质量或其实现或其他细节(如是否连续2次rand()调用可以返回相同的值.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  unsigned int i;
  int r1 = rand();
  int r2 = rand();
  for(i = 0; ; i++) {
    if (r1 == r2) {
        printf("Oops. rand() = %d; i = %d\n", r1, i);
    }
    r1 = r2;
    r2 = rand();
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @bits_international:手册或标准中的定义比程序执行的结果更具权威性.对于我们所知的所有(不参考`rand()`的实际定义),这种行为可能是visual studio实现中的错误,或者程序可能具有未定义的行为. (12认同)
  • 只是一个挑剔,但看起来这可能会错过很多随机的连续数字.它只检查奇数呼叫是否与下一个偶数相同,而不是偶数呼叫与下一个呼叫相同.你最终找到了一个,但很有可能有一个早期的案例. (6认同)
  • @Mankarse:这个程序表明OP问题的答案是肯定的:OP询问它是否会发生,而这个答案表明它可以.OP没有询问标准是否允许这种行为.即使这是MSVC中的一个错误,它仍然会回答这个问题.(当然,对于答案来说,这也是有用的,如果它是一个bug.) (3认同)

Goh*_*han 30

我做了我的研究

发现我的compiler(msvc10)的rand实现确实使用了线性同余生成器,就像其他c/c ++编译器一样

线性同余发生器

线性同余生成器使用递归方法.

使用

ptd - > _ holdrand(n)永远不会等于ptd - > _ holdrand(n + 1),但mod结果将相等.

msvc实施

@nos显示结果

return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) & 0x7fff );

ptd->_holdrand = 2375716238;
return 3482; (2375716238 >> 16) % 32768
ptd->_holdrand = 228240921;
return 3482; (228240921 >> 16) % 32768
Run Code Online (Sandbox Code Playgroud)

最后的答案是rand()将作为我的直觉两次返回相同的值.

  • 你做你的研究很好,但这通常是发布一个问题的步骤(在stackoverflow上几乎没有人遵守的规则). (27认同)
  • 用一些数学作为答案来补充你自己的问题的+1.就像@Shahbaz说的那样,最好在问题出现之前进行这种研究,以避免*如果找到你想要的东西就要问*,但是最好在SO(我认为)上提出这样的参考问题. (5认同)
  • 但是,经常这些答案会暗示要做什么研究,所以如果不仔细阅读问题的答案,研究的尝试就会失败.有时答案会给出一个不完整的答案,而提问者对完整答案比其他人更感兴趣,可以将其作为一个开始.发布改进的答案有益于每个人.发布后的研究比发布后的研究更好. (4认同)
  • @Shahbaz我不同意.我认为,如果一个问题可能产生对其他用户有帮助的信息,那么发布它是好的,只要它不是重复的.这绝对是个问题. (3认同)

dan*_*n04 8

一个理想的随机rand()函数,如果被调用两次,每次都会返回相同的结果,概率为1.0 / RAND_MAX.

rand()不是真正的随机数发生器.它是伪随机数发生器(PRNG),通常是线性同余类型.

连续呼叫时不得重复PRNG 的内部状态 ; 如果确实如此,rand()将永远陷入同一个数字.这可能发生在设计不佳的算法中,例如中间方法.

但是,一些(但不是全部)PRNG实现在其内部状态中具有比在其输出中更多的位.例如,java.util.Random使用48位内部状态,但仅包括其输出中最重要的32位.在这种情况下,(至少在理论上)可以连续两次获得相同的输出而不具有相同的内部状态.


gna*_*729 6

一个好的随机数生成器有时应该连续两次返回相同的值.假设它返回正整数0 <= r <2 ^ 31.对于完美的随机数发生器,两个连续数字相同的可能性大约为20亿.在1000亿次通话中没有获得两个相同数字的机会大约是10 ^ 15中的一个.