【问题标题】:Identical Random Numbers Generated in C++在 C++ 中生成的相同随机数
【发布时间】:2013-09-22 21:54:49
【问题描述】:

我已经为此撞了半个小时,不知道出了什么问题。 我正在尝试生成 10 个随机数 1-100 的列表。但是当我运行它时,它们都会出现相同的数字。这是非常令人沮丧的!我以为是因为这个数字仍然存储在RAM中,但是将随机数和变量重新随机化3次后,它仍然是相同的数字。我做错了什么?

代码:

main() {
    int i;
    int randnum;
    srand(time(NULL));
    randnum = rand() % 2;
    for (i = 0; i < 10; i++) {
        srand(time(NULL));
        randnum = rand() % 100 + 1;
        srand(time(NULL));
        rand();
        list[i] = randnum;
        srand(time(NULL));
        randnum = rand() % 100 + 1;
        srand(time(NULL));
        rand();
    }
    srand(time(NULL));
    randnum = rand() % 100 + 1;
}

【问题讨论】:

  • 另外,如果你真的想使用 rand,不要每次都调用 srand,它会重置序列,这意味着你总是会得到第一个数字。
  • @chris: rand() 不是问题,在循环中调用srand() 并使用分辨率为seconds 的种子是问题所在。
  • rand() 可以代替它。您并不总是需要高质量的 PRNG。称其为“有害”是一种误导性的夸张。
  • @chris:Microsoft CRT 中的rand 实现有点可耻,RAND_MAX 只有 32767。

标签: c++ c random


【解决方案1】:

不要多次致电srand()。这段代码可能需要不到一秒的时间来执行,所以每次调用srand(time(NULL)) 时,当时间以秒为单位时,你只需将伪随机数生成器重置为相同的种子,所以你所有的数字都是一样的.

【讨论】:

    【解决方案2】:

    不要使用srand(time(NULL)) 重新初始化生成器。仅在代码开头使用一次。

    【讨论】:

      【解决方案3】:

      你做错了什么是你正在重置随机数生成器的状态。

      它不明显的原因是因为你在使用时间。 time 返回 time_t,根据标准,它是“实现对当前日历时间的最佳近似”。这通常表示自 1970 年 1 月 1 日 00:00 UTC 以来的秒数。现在,您的代码可能会在一毫秒内执行,因此您所有的时间调用都会返回相同的值。

      所以你的代码相当于:

      int const somenum = time(NULL); 
      srand(somenum); //reset state using some seed.
      
      //rand() will always produce the same value after an
      // srand call of the same seed.
      randnum = rand() % 100 + 1; 
      srand(somenum); //reset state using some seed.
      randnum = rand() % 100 + 1; 
      srand(somenum); //reset state using some seed.
      randnum = rand() % 100 + 1; 
      srand(somenum); //reset state using some seed.
      randnum = rand() % 100 + 1; 
      

      要对此进行测试,请在每次调用 rand 之间等待按键,您会发现它们是不同的。

      解决这个问题的方法是在开始时只调用一次 srand(time(NULL))。

      现在,在 C++11 中,还有另一种方式:

      #include <iostream>
      #include <random>  
      
      int main()
      {
          const int rand_max = 20;
          std::default_random_engine rng(std::random_device{}());
          std::uniform_int_distribution<> dist(0, rand_max);
          std::cout<<"This will always be as random a number as your hardware can give you: "<<dist(rng)<<std::endl;
          return 0;
      }
      

      std::random_device 使用内置的硬件随机数生成器(如果可用),因此您不必担心随时间播种。如果您确实想要一个伪随机数,那么只需使用不同的随机数生成器即可。

      你也可以在 C++11 中control the random number distribution

      【讨论】:

      • 吹毛求疵,但尽管 POSIX 系统将time_t 定义为“自 1970 年 1 月 1 日 00:00 UTC 以来的秒数”,这在人们实际使用的大多数桌面系统上都是如此,C既不要求time_t 从该日期开始计算,也不要求以秒为单位。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-10
      • 2017-07-30
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      • 2015-03-08
      • 1970-01-01
      相关资源
      最近更新 更多