如何使用<random>替换rand()?

Die*_*ühl 30 c++ random c++11

C++ 11引入了<random>带有随机数引擎和随机分布声明的头文件.那很好 - 取代那些用途的时间rand()往往会以各种方式出现问题.但是,如何更换它似乎远非显而易见

srand(n);
// ...
int r = rand();
Run Code Online (Sandbox Code Playgroud)

基于声明,似乎可以构建如下的统一分布:

std::default_random_engine engine;
engine.seed(n);
std::uniform_int_distribution<> distribution;
auto rand = [&](){ return distribution(engine); }
Run Code Online (Sandbox Code Playgroud)

这种方法似乎相当复杂,并且肯定是我不记得的东西,不像使用srand()rand().我知道N4531,但即使这样看起来仍然非常复杂.

是否有一个相当简单的方式来代替srand()rand()

Dav*_*men 16

是否有一种相当简单的方法来替换srand()和rand()?

完全披露:我不喜欢rand().这很糟糕,而且很容易被滥用.

C++ 11随机库填补了一个长期缺乏的空白.高质量随机库的问题在于它们经常难以使用.C++ 11 <random>库代表了这方面的巨大进步.几行代码,我有一个非常好的生成器,行为非常好,很容易从许多不同的发行版生成随机变量.


鉴于上述情况,我对你的回答有点异端.如果rand()足够满足您的需求,请使用它.由于糟糕的rand()是(和它是坏的),删除它会代表与C语言的巨大突破.只要确保rand()真正的坏处足以满足您的需求.

C++ 14没有弃用rand(); 它只是弃用了C++库中使用的函数rand().虽然C++ 17可能会弃用rand(),但它不会删除它.这意味着你还有几年才会rand()消失.在C++委员会最终rand()从C++标准库中删除时,您将退休或切换到其他语言的可能性很高.

我正在创建随机输入来使用类似的东西对std :: sort()的不同实现进行基准测试 std::vector<int> v(size); std::generate(v.begin(), v.end(), std::rand);

您不需要加密安全的PRNG.你甚至不需要Mersenne Twister.在这种特殊情况下,rand()可能足以满足您的需求.


更新
有一个很好的简单替代rand(),并srand()在C++ 11随机库:std::minstd_rand.

#include <random>
#include <iostream>

int main ()
{
    std:: minstd_rand simple_rand;

    // Use simple_rand.seed() instead of srand():
    simple_rand.seed(42);

    // Use simple_rand() instead of rand():
    for (int ii = 0; ii < 10; ++ii)
    {
        std::cout << simple_rand() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

该函数std::minstd_rand::operator()()返回一个std::uint_fast32_t.但是,该算法将结果限制在1到2 31 -2之间,包括1和2 31 -2.这意味着结果将始终安全地转换为a std::int_fast32_t(或intif int至少32位长).


jtb*_*des 6

pcg-random.orgrandutils的Melissa O'Neill 怎么

介绍性博客文章:

randutils::mt19937_rng rng;

std::cout << "Greetings from Office #" << rng.uniform(1,17)
          << " (where we think PI = "  << rng.uniform(3.1,3.2) << ")\n\n"
          << "Our office morale is "   << rng.uniform('A','D') << " grade\n";
Run Code Online (Sandbox Code Playgroud)


5go*_*der 6

假设您想要C风格randsrand函数的行为,包括它们的怪癖,但随机性很好,这是我能得到的最接近的行为.

#include <random>
#include <cstdlib>  // RAND_MAX  (might be removed soon?)
#include <climits>  // INT_MAX   (use as replacement?)


namespace replacement
{

  constexpr int rand_max {
#ifdef RAND_MAX
      RAND_MAX
#else
      INT_MAX
#endif
  };

  namespace detail
  {

    inline std::default_random_engine&
    get_engine() noexcept
    {
      // Seeding with 1 is silly, but required behavior
      static thread_local auto rndeng = std::default_random_engine(1);
      return rndeng;
    }

    inline std::uniform_int_distribution<int>&
    get_distribution() noexcept
    {
      static thread_local auto rnddst = std::uniform_int_distribution<int> {0, rand_max};
      return rnddst;
    }

  }  // namespace detail

  inline int
  rand() noexcept
  {
    return detail::get_distribution()(detail::get_engine());
  }

  inline void
  srand(const unsigned seed) noexcept
  {
    detail::get_engine().seed(seed);
    detail::get_distribution().reset();
  }

  inline void
  srand()
  {
    std::random_device rnddev {};
    srand(rnddev());
  }

}  // namespace replacement
Run Code Online (Sandbox Code Playgroud)

这些replacement::*功能可以完全像std::*对应的功能一样使用<cstdlib>.我添加了一个srand不带参数的重载,并使用从a获得的"真实"随机数为引擎播种std::random_device.随机性的"真实"当然是实现定义的.

引擎和分发作为thread_local static实例保存,因此它们跨多个调用携带状态,但仍允许不同的线程观察可预测的序列.(这也是一种性能提升,因为您不需要重新构建引擎或使用锁定并可能摧毁其他人的现金.)

我已经习惯std::default_random_engine因为你做了但我不太喜欢它.Mersenne Twister发动机(std::mt19937std::mt19937_64)产生更好的"随机性",并且令人惊讶地,也观察到更快.我不认为任何兼容程序必须依赖于std::rand使用任何特定类型的伪随机引擎实现.(即使它确实如此,实现可以自由地定义std::default_random_engine为他们喜欢的任何东西,所以你必须使用类似的东西std::minstd_rand.)

  • 虽然这段代码令人印象深刻且IMO设计得很好,但我认为这不是"替换srand()和rand()的相当简单的方法"...... (2认同)