如何获取rand()(C ++)的源代码?

时间:2013-09-23 22:13:40

标签: c++ random

我是编程新手。

我想确切知道rand()的作用。

仅搜索会产生有关其用法的示例。但没有人解释函数如何生成随机数的每一步。他们将rand()视为黑盒子。

我想知道rand()正在做什么;每一步。

是否有资源可以让我查看rand()的确切内容? 这是所有开源的东西不是吗?如果没有消息来源,我会接受拆解。

我知道它会返回一个随机数,但它是如何生成该数字的?我想看看每一步。

谢谢。

7 个答案:

答案 0 :(得分:16)

以下是the current glibc implementation

/* Return a random integer between 0 and RAND_MAX.  */
int
rand (void)
{
  return (int) __random ();
}

这没什么帮助,但__random最终会调用__random_r

/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
   same in all the other cases due to all the global variables that have been
   set up.  The basic operation is to add the number at the rear pointer into
   the one at the front pointer.  Then both pointers are advanced to the next
   location cyclically in the table.  The value returned is the sum generated,
   reduced to 31 bits by throwing away the "least random" low bit.
   Note: The code takes advantage of the fact that both the front and
   rear pointers can't wrap on the same call by not testing the rear
   pointer if the front one has wrapped.  Returns a 31-bit random number.  */

int
__random_r (buf, result)
     struct random_data *buf;
     int32_t *result;
{
  int32_t *state;

  if (buf == NULL || result == NULL)
    goto fail;

  state = buf->state;

  if (buf->rand_type == TYPE_0)
    {
      int32_t val = state[0];
      val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
      state[0] = val;
      *result = val;
    }
  else
    {
      int32_t *fptr = buf->fptr;
      int32_t *rptr = buf->rptr;
      int32_t *end_ptr = buf->end_ptr;
      int32_t val;

      val = *fptr += *rptr;
      /* Chucking least random bit.  */
      *result = (val >> 1) & 0x7fffffff;
      ++fptr;
      if (fptr >= end_ptr)
    {
      fptr = state;
      ++rptr;
    }
      else
    {
      ++rptr;
      if (rptr >= end_ptr)
        rptr = state;
    }
      buf->fptr = fptr;
      buf->rptr = rptr;
    }
  return 0;

 fail:
  __set_errno (EINVAL);
  return -1;
}

答案 1 :(得分:13)

答案 2 :(得分:3)

您可以浏览C标准的不同实现的源代码。

之前已回答过这个问题,您可能会在What common algorithms are used for C's rand()?

找到您要找的内容

该答案为glibc实现rand()

提供了代码

答案 3 :(得分:2)

我想,THIS正是您所寻找的。它包含随机函数的详细解释,以及简单的C程序来理解算法。

编辑:

您也应该检查THIS。可能重复。

答案 4 :(得分:2)

好吧,我相信rand来自C标准库,而不是C ++标准库。两个库都没有一个实现,有几个。

你可以去this page之类的地方查看glibc的源代码,glibc是大多数Linux发行版上使用的c库。对于glibc,您可以在stdlib下的源文件中找到它,例如rand.crandom.c

不同的实现,例如uClibc可能更容易阅读。 libc / stdlib文件夹下的Try here

答案 5 :(得分:1)

最简单的合理良好的伪随机数生成器是Linear Congruential Generators (LCGs)。这些是公式的迭代,例如

X_{n+1} = (a * X_n  +  c) modulo m

选择常数a,c和m以给出不可预测的序列。 X_0是随机种子值。存在许多其他算法,但这可能足以让你前进。

非常好的伪随机数生成器更复杂,例如Mersenne Twister

答案 6 :(得分:0)

如果我错了请纠正我,但是虽然this answer指向了部分实现,但我发现rand()中使用的stdlib还有更多,它来自{{ 1}}。从从 2.32 version 获得的 here 中,[glibc][2] 文件夹包含一个 stdlib 文件,该文件说明使用了简单的线性同余算法。该文件夹还有 random.crand.c,可以向您展示更多的源代码。包含在同一文件夹中的 rand_r.c 将显示用于 stdlib.h 等宏的值。

<块引用>

/* 改进的随机数生成包。除了 标准的 rand()/srand() 接口,这个包也有 特殊状态信息接口。调用 initstate() 例程 带有种子、字节数组和字节数的计数 被传入;然后将此数组初始化为包含 具有那么多状态的随机数生成信息 信息。状态信息量的合适大小是 32、64、128 和 256 字节。可以通过调用来切换状态 具有与初始化相同的数组的 setstate() 函数 初始化状态()。默认情况下,包以 128 字节的状态运行
信息并生成比线性更好的随机数
同余生成器。如果状态信息量较少 超过 32 个字节,一个简单的线性同余 R.N.G.用来。 在内部,状态信息被视为一个 long 数组; 数组的第零个元素是 R.N.G.正在使用 (小整数);数组的其余部分是状态 R.N.G. 的信息因此,32 字节的状态信息 将提供 7 长的状态信息,这将允许 七次多项式。 (注:状态的第零个字
信息中还存储了一些其他信息;参见 setstate 详情)。随机数生成技术是一种线性 反馈移位寄存器方法,采用三项式(因为有 以这种方式总结的术语较少)。在这种方法中,最少 状态表中所有数字的有效位将作为 线性反馈移位寄存器,周期为 2^deg - 1 (其中 deg 是所使用的多项式的次数,假设 多项式是不可约的和原始的)。更高的顺序 位将有更长的周期,因为它们的值也是 受低位伪随机执行的影响。
发电机的总周期约为 deg*(2deg - 1);因此 状态信息量翻倍对
的影响巨大 发电机周期。注意: deg*(2
deg - 1) 是一个 近似仅适用于大度,当移位周期 注册是主导因素。当 deg 等于 7 时, 周期实际上比预测的 7*(2**7 - 1) 长得多 这个公式。 */