【问题标题】:Does stdlib's rand() always give the same sequence?stdlib 的 rand() 是否总是给出相同的序列?
【发布时间】:2011-03-31 01:11:55
【问题描述】:

我非常喜欢能够重复生成同一组伪随机数据,尤其是在调整实验代码时。通过观察我会说rand() 似乎每次都给出相同的数字序列*。

是否保证在同一台机器上/不同机器/不同架构上重复执行?

*显然是同一个种子。

【问题讨论】:

    标签: c random std


    【解决方案1】:

    是的,给定相同的程序环境。来自 C 标准 §7.20.2.2/2,

    srand 函数将参数用作新伪随机数序列的种子,这些伪随机数序列将在后续调用rand 时返回。 如果 srand 被调用时使用相同的种子值,则伪随机数序列应重复。 如果在调用 srand 之前调用 rand,则相同序列应在第一次调用 srand 时生成,种子值为 1。

    当然,这假设它使用相同的实现细节(即相同的机器,相同的库在相同的执行周期)。 C 标准不强制规定标准的随机数生成算法,因此,如果您使用不同的 C 标准库运行程序,可能会得到不同的随机数序列。

    如果您需要具有给定种子的可移植且有保证的随机数序列,请参阅问题Consistent pseudo-random numbers across platforms

    【讨论】:

    • 好的。我同意对于特定的运行时库,序列是相同的。因此,一旦构建了应用程序(针对特定的运行时版本),它将始终生成相同的序列。但这是否会影响运行时的不同版本(即跨操作系统/架构/运行时版本)等。如果这样做意味着标准定义了 rand() 算法的精确实现(否则两个独立的操作系统将如何确保他们符合)。
    • 它不会扩展到不同版本的运行时 - 如果您动态链接到 rand() 的实现,它可能会在不重建任何东西的情况下采取不同的行动。
    • @Martin:但这会影响到不同版本的运行时——不。实际上,更新是否会改变行为取决于运行时。
    • 感谢您的回答!调整阶段只发生在一台机器上(为了完整性,我添加了扩展问题)。
    • 标准中的语言只保证每次调用 srand() 时都将获得相同的序列在一次程序执行期间(“如果 srand 被调用...” 意味着它发生在同一个程序中)。实现在程序启动时选择“主种子”是符合要求的,这会在每次程序运行时扰乱不同的算法。
    【解决方案2】:

    保证为传递给srand() 的相同种子提供相同的序列 - 但仅在程序的单次执行期间。一般来说,如果一个实现可以选择行为,则没有具体要求该选择在后续执行中保持不变。

    在每次程序启动时选择一个“主种子”,并使用它以每次程序启动时不同的方式扰乱伪随机数生成器,这将是符合要求的。

    如果您希望获得更多确定性,您应该在程序中实现带有特定参数的 PRNG。

    【讨论】:

      【解决方案3】:

      没有。

      C 标准说:

      如果 srand 则以相同的方式调用 种子值,序列 伪随机数应为 重复。

      但它没有说明伪随机数序列实际上是什么 - 所以它在不同的实现中有所不同。

      唯一的保证是rand() 将为给定的种子提供相同的数字序列对于给定的实现。无法保证在不同机器或不同架构之间的顺序是相同的 - 而且几乎可以肯定不会。

      【讨论】:

        【解决方案4】:

        如果您需要使用完全相同的一组伪随机数进行实验,您可以使用srand 生成一长串随机数并将它们写入文件/数据库。然后,编写一个可移植的“随机数生成器”函数,从该文件中按顺序返回值。这样,无论平台、srand 实现或种子值如何,您都可以放心使用相同的输入数据。

        【讨论】:

        • 好主意。如果我有这样做的要求,我肯定会采取这种方法。我的问题更多是出于好奇而不是对已知序列的需要。
        • 或者你可以自己写一个随机函数?
        【解决方案5】:

        当切换到不同的机器/运行时/无论你可能不走运。 drand48 系列函数还有另一种可能的选择。这些被标准化以在所有机器上使用相同的算法。

        【讨论】:

          【解决方案6】:

          如果您在 UNIX/Linux 环境中,您可以在手册页中看到 drand48()srand48() 如果不是,您可以看到 @987654321 @ 代表 C 语言。 原型可以在 /usr/include/stdlib.h 中找到。 第一个使用模拟中经常使用的线性同余方法。

          如果您为 srand48() 提供相同的种子,即 srand48(2),然后将 dran48() 放入 for 循环中,那么每次的序列都是相同的。 即

          include stdio.h
          include stdlib.h
          double drand48();
          int main(void){
              int i;
              double rn;
              srand48(2);
              for(i=0; i<10; i++){
                  randNum = drand48();
                  printf("%.6l\n", randNum);
                  return 0;
          }
          

          【讨论】:

            猜你喜欢
            • 2013-03-11
            • 1970-01-01
            • 1970-01-01
            • 2011-06-19
            • 2016-06-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-23
            相关资源
            最近更新 更多