C中的简单随机数生成器不起作用

时间:2012-05-06 00:41:34

标签: c random

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char** argv) {


    srand(time(NULL));
    int r = rand();

    printf("%d\n", r);

    return (EXIT_SUCCESS);
}

当我在几秒钟的时间内重复运行此代码片段时,我得到了一系列增加的数字,例如213252683,213975384,214193875,214445980。在我看来,我只是打印出系统时间 - 当我添加行printf("%d\n", time(NULL))时,似乎可以确认该假设;到代码。我究竟做错了什么?我在Mac OS X 10.6.1(Snow Leopard)上运行,但我只使用标准库功能,所以它不应该有所作为。谢谢!

5 个答案:

答案 0 :(得分:3)

伪随机数生成为源自初始种子的混沌序列。 srand通过设置此种子来初始化随机性。显然,序列中的第一个随机数是种子本身 - 这是您设置的time()值。

这就是为什么生成随机序列的正确方法是在程序开始时只调用srand()一次,然后只调用rand()(好吧,也许直到序列)开始循环,这不应该太快发生,但这取决于生成函数)。正如您所见,过于频繁地调用srand()会使随机性恶化。

答案 1 :(得分:1)

如果它有帮助我通常会这样使用它:

int rand_between(int min, int max)
{
  static int flag = 1;
  FILE *urandom;
  unsigned int seed;

  if (flag)
    {
      flag = 0;
      if (!(urandom = fopen ("/dev/urandom", "r")))
      fprintf(stderr, "Cannot open /dev/urandom!\n");
      fread(&seed, sizeof(seed), 1, urandom);
      srand(seed);
    }
  return ((int)rand() % (max - min)) + min;
}

获取随机大写字母:

char letter = (char)rand_between('A', 'Z');

答案 2 :(得分:0)

  

当我在几秒钟内重复运行此代码片段时,   我得到了一系列越来越多的数字,比如213252683,213975384,   214193875,214445980。

我无法重现这一点。在我的系统(Debian Linux)上,我得到了没有订购的数字。此外,结果与您在打印time(NULL)时获得的结果不同。

这应该是这样的:您正在使用当前时间(以秒为单位)为随机数生成器播种。因此,只要时间(低至秒)相同,程序就会打印相同的结果。

  

我做错了什么?

嗯,这取决于你想要什么。如果你想要每次运行的随机数,你需要一个更好的随机源。您可以尝试gettimeofday等具有更高分辨率的函数(我相信通常为ms)。此外,混合使用其他随机来源,例如您的流程ID。

在大多数程序中,您看到的效果没有问题,因为通常只在开始时调用srand(),然后rand()会在每次调用时返回不同的数字。

如果你想要“安全”(即不可预测的)随机数,那就是另一个游戏。参见例如Wikipedia了解概述。

答案 3 :(得分:0)

随机数发生器差别很大,因此很难在其他机器上重现。看起来您实现的第一个数字只是种子值。例如,在我的情况下,第一个数字似乎与种子线性相关。通常,您将在程序中调用srand一次,并在rand调用多次,并且连续调用将获得更随机的结果。如果你想避免这个问题,那么做是合理的:

srand(time(NULL));
rand();
int r = rand();

printf("%d\n", r);

第一个rand调用确保种子不会返回,下一个应该选择看起来更随机的内容。请注意,如果您在足够短的时间跨度内运行程序两次(两次运行中time(NULL)相同),您将得到完全相同的结果。这绝对是预期的 - 如果这是一个问题,使用不同的种子值(pid + time可能是一个好的开始,或者只是一个更高分辨率的时间)。

答案 4 :(得分:0)

你应该使用random()而不是rand()。它在各方面都优于rand(),它也包含在stdlib中。
请尝试以下代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
int r = random();
printf("%d\n", r);
return (EXIT_SUCCESS);
}