【问题标题】:A problem with random number generation随机数生成的问题
【发布时间】:2010-03-10 19:31:47
【问题描述】:

我正在学习编程课程,我们使用的是 C++。 我们有一个任务,在某些时候,我们需要编写一个函数,该函数将在 [upper, lower] 区间中返回一个随机数。我使用了以下内容:

lower + (int) (upper * (rand() / (RAND_MAX + 1.0)));

我没有忘记使用srand((unsigned int) time(0))更改srand

但是,我每次都得到相同的值!我向我的教授寻求帮助,经过一番调查,他发现rand() 生成的第一个数字并不是那么随机......高阶位保持不变,并且由于此实现使用它们,最终结果是'和我预期的不太一样。

有没有比丢弃第一个值或使用余数来实现我想要的更优雅、更简单的解决方案?

非常感谢您的关注!

~弗朗西斯科

编辑:谢谢大家的意见。我不知道rand() 是一个如此糟糕的 RNG:P

【问题讨论】:

  • rand() 不是已经过时了吗?我认为这些天每个人都应该使用random()
  • lower + rand() % (upper - lower + 1) 有什么问题?为什么不想使用余数?
  • 只是插话,我也注意到了这一点。如果您实际上只是在每次发现它不完全相同时打印出第一个 rand() ,但这些数字都相当接近。例如,现在当我连续多次启动一个程序时,我得到的数字都在 23000 范围内,例如作为第一个数字。之后数字更加随机。我总是像你提到的那样丢弃第一个 rand() 数字。
  • 你确定是高位保持不变吗? “C 中的数字食谱”一书暗示它是相反的,即低阶位的随机性要小得多。 rand(3) 手册页 (linux.die.net/man/3/rand) 实际上引用了那本书。
  • Void:是的,我知道低阶位应该不那么随机。但是,在这种特殊情况下,我发现生成的第一个数字正好相反。

标签: c++ random


【解决方案1】:

鉴于 rand() 不是一个非常强大的随机数生成器,标准方法添加的少量偏差可能不是问题:(higher-lower)当然需要小于 MAX_RAND。

lower + rand() % (higher-lower+1);

被一个错误解决了。

【讨论】:

  • lower + rand() % (higher-lower+1);
  • 应该是lower + rand() % (higher-lower + 1); 出于学术上的好奇,我想为这个问题找到一个不同的解决方案,但感谢您的意见。 :)
【解决方案2】:

rand() 不是一个好的随机数生成器。除了您观察到的问题之外,它的周期长度可能非常短。

考虑使用gsl random number generators 之一。

【讨论】:

    【解决方案3】:

    根据您使用的操作系统,除了rand() 之外,您还可以使用random()。这会产生比rand() 更好的伪随机数。检查<stdlib.h> 和/或man 3 random

    【讨论】:

      【解决方案4】:

      你的代码很好,但你应该替换

      lower + (int) upper * (rand() / (RAND_MAX + 1.0));
      

      lower + (int) (upper - lower + 1)*(rand() / (RAND_MAX + 1.0));
      

      以下代码在我的机器上运行良好:

      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      
      #define lower 10
      #define upper 20
      
      int main(void)
      {
          int i;
          int number;
      
          srand(time(0));
          for(i=0; i<10; i++)
          {
              number = lower + (int) (upper - lower + 1)*(rand() / (RAND_MAX + 1.0));
              printf ("%d\n", number);
          }
      
          return 0;
      }    
      

      当然,由于time(0) 给出了当前时间以秒为单位,同一秒内的两次执行会给出相同的结果。

      【讨论】:

      • "rand() 以秒为单位给出当前时间" - 这是一个奇怪的实现。 :P
      • @Bill:哦,呃,好吧......它仍然是一个未记录的功能。最高机密。不要告诉任何人
      【解决方案5】:

      C++0x 随机数库(TR1 和 Boost 中也有)终于解决了 rand 的一些讨厌的问题。它允许获得可用于正确播种的真正随机性(random_device),然后您可以使用快速且良好的伪随机生成器(mt19937),您可以对其应用合适的分布(例如,uniform_int for min-max range with equal每个值的概率)。

      它也不像 rand() 那样使用全局隐藏状态,所以在多线程程序中不会有任何问题。

      由于所有的模块化,它比简单地调用 rand 更难使用,但好处仍然大大超过了更陡峭的学习曲线。

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 2016-05-26
        • 2013-06-03
        • 2017-04-10
        • 2014-07-20
        • 2018-10-11
        • 1970-01-01
        • 2014-06-14
        相关资源
        最近更新 更多