【问题标题】:Implementation of random number generator [duplicate]随机数生成器的实现
【发布时间】:2012-08-10 09:49:40
【问题描述】:

可能重复:
How does a random number generator work?

我正在寻找 C/C++ 中随机数生成器的内部实现。基本上我很想知道,调用 rand() 时究竟会发生什么。毕竟机器都遵循一定的指令,怎么可能是随机的!
编辑:想知道如何在 C/C++ 中实现一个。

【问题讨论】:

标签: c++ c random implementation


【解决方案1】:

它们是 伪随机 数字生成器,而不是真正的随机数字生成器。这通常是一件的事情,因为它可以让您更轻松地重现涉及“随机”数字的错误。

可以获取随机数生成器,例如在 Linux 下读取 /dev/random,但 C 库附带的普通生成器通常没有。

最简单的是线性同余生成器,其中:

n(x+1) = n(x) * A + C modulo M

with suitably chosen values of A, C and M.

Wikipedia's page on LCGs 给出了各种实现使用的一些示例值。例如,那里列出的glibca = 1103515245, c = 12345, m = 2^31,所以很简单:

static unsigned int seed = 1;
void srand (int newseed) {
    seed = (unsigned)newseed & 0x7fffffffU;
}
int rand (void) {
    seed = (seed * 1103515245U + 12345U) & 0x7fffffffU;
    return (int)seed;
}

除此之外:glibc 实现中仍然有这个生成器(称为 0 型生成器),但它也有一个更高级的三项式生成器,它(可能)更好。

还有更复杂的(例如梅森捻线机),它们的循环时间(开始重复之前的时间)要长得多。

任何真正的随机生成器都必须使用真正随机的输入源,这就是为什么/dev/random 有时会阻塞(“等待熵”)而/dev/urandom 不会。

“真正的”随机源可能会受到击键之间的时间、用户输入的数据、网络数据包的内容、磁盘 I/O 模式、ICMP 响应通过网络返回所需的时间以及各种其他因素的影响奇妙的,大多是非确定性的东西。

除非你对加密非常感兴趣,否则普通的随机数生成器就可以了。

【讨论】:

    【解决方案2】:

    正如我在 cmets 中所说,RAM 机器的随机生成器并不是真正随机的,它们是pseudo-random

    大家可以随时查看java.util.Random的java源码。

    具体来说 - next(int bits) 方法是您正在寻找的。​​p>

    protected int next(int bits) {
          long oldseed, nextseed;
          AtomicLong seed = this.seed;
          do {
                oldseed = seed.get();
                nextseed = (oldseed * multiplier + addend) & mask;
          } while (!seed.compareAndSet(oldseed, nextseed));
          return (int)(nextseed >>> (48 - bits));
    }
    

    (*) 这个答案适合之前版本的问题,它被标记为 java 并且没有专门询问 C++。

    【讨论】:

      【解决方案3】:

      这是一个简单的伪随机算法:

      //generates pseudo random series of numbers 0...RAND_MAX - 1 with uniform distribution, starting with 0
      
      static const int A = 15342; // any number in (0, RAND_MAX)
      static const int C = 45194; // any number in [0, RAND_MAX)
      static const RAND_MAX = 100000;
      
      int rand()
      {
          static int prev = 0; //seed. any number in [0, RAND_MAX)
          prev = ( prev * A + C ) % RAND_MAX;
          return prev;
      }
      

      您可以在这里阅读更多内容:http://en.wikipedia.org/wiki/Linear_congruential_generator

      【讨论】:

      • 顺便说一下,A、C 和 RAND_MAX 的值选择得非常糟糕。您所有的数字都将是 5000 的倍数 :-) 相对质数往往会提供更好的分布。
      • @paxdiablo:同意,将它们随机化一点)但无论如何它都会给出均匀分布。选择好的数字需要更多的研究
      • 那个静态变量 prev 似乎永远不会更新。
      • @jjmontes:谢谢,已更正
      猜你喜欢
      • 2011-07-03
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-08
      • 2012-11-28
      相关资源
      最近更新 更多