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位长).
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)
假设您想要C风格rand和srand函数的行为,包括它们的怪癖,但随机性很好,这是我能得到的最接近的行为.
#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::mt19937和std::mt19937_64)产生更好的"随机性",并且令人惊讶地,也观察到更快.我不认为任何兼容程序必须依赖于std::rand使用任何特定类型的伪随机引擎实现.(即使它确实如此,实现可以自由地定义std::default_random_engine为他们喜欢的任何东西,所以你必须使用类似的东西std::minstd_rand.)