【问题标题】:What's the standard way for getting uniformly distributed random integers in C++?在 C++ 中获得均匀分布的随机整数的标准方法是什么?
【发布时间】:2012-05-29 11:08:12
【问题描述】:

是否有一个函数可以在某个指定范围内均匀获得分布的伪随机整数?我可以使用rand 编写自己的函数,但这似乎很常见,STL 中可能有一些内容。

【问题讨论】:

    标签: c++ random


    【解决方案1】:

    使用std::generate_nboost生成一个或指定数量的整数域上均匀分布的随机变量:

    #include <iostream>
    #include <algorithm>
    #include <boost/random.hpp>
    
    /*
     * 
     */
    int main(int argc, char** argv) {
        boost::mt19937 rand_generator(std::time(NULL));
        boost::random::uniform_int_distribution<> int_distribution(0, 100);
    
        //Need to pass generator
        std::cout << int_distribution(rand_generator) << std::endl;
    
        //Associate generator with distribution
        boost::random::variate_generator<boost::mt19937&,
                boost::random::uniform_int_distribution<>
                > int_variate_generator(rand_generator, int_distribution);
    
        //No longer need to pass generator
        std::cout << int_variate_generator() << std::endl;
        std::generate_n( std::ostream_iterator<int>(std::cout, ","), 3, int_variate_generator);
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      要在 C++ 中生成伪随机数,一个很好的选择是使用 Mersenne twister 伪随机数生成器引擎:来自@987654325 的std::mt19937 @标头。

      我们可以把这个引擎想象成一个黑盒,它会吐出高质量的随机位

      然后,这些随机位可以在某些整数输出中使用分布进行整形;特别是,为了获得均匀分布的伪随机数,可以使用 std::uniform_int_distribution

      请注意,引擎对象必须使用种子进行初始化。
      std::random_device 可用于此目的。

      所以,这个过程可以概括为三个逻辑步骤:

      1. 创建std::random_device 的实例,以获取梅森捻线机引擎的非确定性种子
      2. 创建std::mt19937 的实例engine,以获得高质量的伪随机位。
      3. 使用std::uniform_int_distribution塑造这些随机位在均匀分布的整数中。

      可编译的 C++ 代码如下:

      #include <iostream>     // for console output
      #include <random>       // for pseudo-random number generators and distributions
      
      int main()
      {
          // Use random_device to generate a seed for Mersenne twister engine.
          std::random_device rd;    
      
          // Use Mersenne twister engine to generate pseudo-random numbers.
          std::mt19937 engine(rd());
          
          // "Filter" MT engine's output to generate pseudo-random integer values,
          // **uniformly distributed** on the closed interval [0, 99].  
          // (Note that the range is [inclusive, inclusive].)
          std::uniform_int_distribution<int> dist(0, 99);
      
          // Generate and print 10 pseudo-random integers
          for (int i = 0; i < 10; ++i)
          {
              std::cout << dist(engine) << ' ';
          }
          std::cout << std::endl;
      }
      

      有关在 C++ 中生成伪随机数的更多详细信息(包括为什么 rand() 不好好),请参阅 Stephan T. Lavavej 的此视频(来自Going Native 2013):

      rand() Considered Harmful

      【讨论】:

      • +1 确实花了一段时间,但最终合并了。您可能想要编辑您的问题以表明它是合并的一部分,并且也是对 OP 的评论,以便他们理解为什么这个新答案以旧日期弹出。
      • 不知道为什么大家都说梅森龙卷风那么棒,那么“高品质”。它不是。它很复杂,具有巨大的内存占用,并且仍然无法通过 TestU01 BigCrush 测试套件的多次测试。今天有几个更简单、更快、质量更高的 PRNG,它们有足够的周期。
      • @plasmacel:我问过 Stephan T. Lavavej(VC STL 维护者),他确认它是最好的标准 PRNG。您会提出什么更好的替代方案?
      【解决方案3】:

      Boost 提供了许多随机数生成工具。 对于均匀分布,你有这个:

      http://www.boost.org/doc/libs/1_49_0/doc/html/boost/random/uniform_real_distribution.html

      编辑: 已更新以包含新的 C++11 实现。对于整数的情况,这里有参考:

      http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

      一个简单的例子是:

      #include <random>
      #include <iostream>
      int main()
      {
          std::random_device rd;
          std::mt19937 gen(rd());
          std::uniform_int_distribution<> dis(1, 6);
          for(int n=0; n<10; ++n)
              std::cout << dis(gen) << ' ';
          std::cout << '\n';
      }
      

      【讨论】:

      • 它们现在是 C++11 的一部分,因此它们是标准的。
      • @K-ballo 太棒了! C++11 让 C++ 变得更容易:)
      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2014-03-02
      • 2011-08-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      • 1970-01-01
      相关资源
      最近更新 更多