【问题标题】:How does the random number generator work in C?随机数生成器如何在 C 中工作?
【发布时间】:2012-04-07 13:32:47
【问题描述】:

我正在尝试生成 0 到 40(含)之间的随机数。 所以我实现的代码是这样的-

 y=rand()%41;

但是每次我点击编译并点击运行。它输出相同的随机数。 比如说我在一个循环中运行它。

for(i=0;i<4;i++)
{
     y=rand()%41;
     printf("%d ",y);
}

每一次,输出都是相同的 4 个数字。它总是在终端上输出 14,2 等。不管怎样。

所以我的第一个问题是,为什么会这样?

其次,随机数生成器在 C 中是如何工作的?

我认为由于我包含 time.h 库,因此这些数字是通过使用系统时间的一些标准算法生成的。而且由于系统时间是不断变化的,所以每次运行程序时生成的数字也应该会发生变化。

【问题讨论】:

  • 如果使用rand() % x,其中x不除RAND_MAX,分布将不均匀。
  • 但这不是重点。
  • @H2CO3 这就是为什么它是评论,而不是答案。

标签: c random generator


【解决方案1】:

rand() 只生成伪随机数。这意味着每次运行代码时都会得到完全相同的数字序列。

考虑使用

srand(time(NULL))

每次获取不同的数字。事实上,rand 的一个可能实现是

next = next * 1103515245 + 12345;
return (UINT32)(next>>16) & RAND_MAX;

其中next 定义为

static UINT32 next = 1;

调用srand() 会改变next 的初始值,从而改变你得到的“下一个”值。

【讨论】:

  • 其实rand算法是未指定的
  • 我会明确表示,您不应该在每次获得另一个号码时重新播种 rng;您应该只在开始时播种一次,并且可能在您接近 RAND_MAX 请求的数字时再次播种。还值得注意的是,许多 rng 在生成高质量随机值之前需要一个预热期;这通常是 state_size*4。不幸的是,没有办法知道 rand 的实现,所以你不会知道它的状态大小。许多实现都是线性生成器,没有状态。
【解决方案2】:

至于它是如何工作的,这取决于。许多实现使用带有不同参数的Linear Congruential Generator

【讨论】:

    【解决方案3】:

    用于rand 的算法未在 C 标准中指定,

    根据规范,如果您在程序中调用rand 之前不调用srand,就好像调用了srand(1):每次执行程序时,种子值都是1并且生成的序列将始终相同。

    为程序的不同执行设置不同种子的常用方法是使用取决于当前时间的种子,例如:

    srand(time(NULL));  
    

    【讨论】:

      【解决方案4】:

      这实际上是一个关于 comp.lang.c 的常见问题解答。这是他们建议的解决方案:

      (int)((double)rand() / ((double) RAND_MAX + 1) * N )
      

      N 是随机数范围的上限。这是因为糟糕的 C 编译器上的低位是“令人震惊的非随机”。这并不能解决使用 srand() 的需要。请注意,但是应该在循环的 outside 中调用 srand( time(NULL) ) ... time() 的分辨率为 1 秒,因此在循环内部调用它会重新初始化您的随机数生成器连续多次生成同一个种子。

      对此的需求可能在很大程度上是历史性的,我确信现代编译器可能没有随机数生成器会发出非常糟糕的随机数,但我记得使用 Borland C 编译器编写了一个程序,它会循环大约我反复使用rand() % 41时的5个号码。

      【讨论】:

        【解决方案5】:

        原因是 rand() 每次运行时都使用相同的种子。你必须自己播种。 srand ( time(NULL) );` 通常用于初始化随机种子。

        【讨论】:

          【解决方案6】:

          它是由传递种子的参数生成的。要生成不同的数字,请在调用 rand() 函数之前添加:

          srand (time(NULL));
          

          这会生成一个新的随机种子。

          你应该有这个库:#include &lt;time.h&gt; 如果你仍然有错误使用这个库:#include &lt;stdlib.h&gt;

          【讨论】:

          • 每次调用rand函数时添加?
          • 是的,我想是的。无论如何尝试其他方式。
          • 您不必这样做。每个种子负责一个伪随机数序列。
          • 不,您在程序启动时运行 srand() 一次。如果有兴趣,应该是:en.wikipedia.org/wiki/Pseudorandom_number_generator
          • @nos 谢谢,我不确定。
          猜你喜欢
          • 2010-12-15
          • 2012-11-12
          • 1970-01-01
          • 1970-01-01
          • 2012-11-06
          • 1970-01-01
          • 1970-01-01
          • 2011-01-24
          相关资源
          最近更新 更多