【问题标题】:How can I get the sourcecode for rand() (C++)?如何获取 rand() (C++) 的源代码?
【发布时间】:2013-09-28 23:18:21
【问题描述】:

我是编程新手。

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

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

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

是否有资源可以让我准确了解 rand() 的作用? 这都是开源的东西不是吗?没有来源我就去拆机了。

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

谢谢。

【问题讨论】:

  • 你关心什么系统?大概有多少环境就有多少实现。
  • 您的编译器可能有可用的运行时库源。那里可能可以找到实现。
  • rand 使用伪随机生成器,因此阅读 PRNG 背后的理论比任何源代码都更有启发性
  • This paper 是经典之作,并不难理解,它涵盖了基础知识,尽管按照现代标准来看它是原始的。 (但rand() 也是如此。)

标签: c++ random


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 好的。我对编程很陌生(约 3 天!)所以我不知道要搜索什么。我在这里找到了我需要研究的实现:bioen.okstate.edu/Home/prashm%20-%20keep/prashant/…
      • @user2071506 哦,好吧,我用谷歌搜索了GNU libc rand,字面意思。它也提出了 SO 链接。没有一个链接来自前 12 次点击之外。 ://
      • @sehe GNU libc rand 很难。 sourcecode for rand() (C++) 从标题中直接复制也给了我很好的结果。
      【解决方案4】:

      我猜,THIS 就是您要找的。它包含对随机函数的详细解释,以及用于理解算法的简单 C 程序。

      编辑:

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

      【讨论】:

        【解决方案5】:

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

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

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

        真正好的伪随机数生成器更复杂,比如Mersenne Twister

        【讨论】:

        • 想解释一下-1吗?
        【解决方案6】:

        这里是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;
        }
        

        【讨论】:

          【解决方案7】:

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

          这个问题之前已经回答过了,你可以在What common algorithms are used for C's rand()?找到你想要的东西

          该答案为 glibc 的 rand() 实现提供了代码

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-08-10
            • 1970-01-01
            • 2011-06-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-02
            相关资源
            最近更新 更多