新的C++ 11标准有一整章专门用于随机数生成器.但是,我如何执行过去像这样编码的最简单,最常见的任务,但不使用标准C库:
srand((unsigned int)time(0)); int i = rand();
是否可以使用开箱即用的随机数引擎,分布和种子的合理默认值?
CB *_*ley 30
你应该可以这样做:
std::default_random_engine e((unsigned int)time(0));
int i = e();
Run Code Online (Sandbox Code Playgroud)
default_random_engine依赖于实现的质量.你也可以使用std::min_rand0或std::min_rand.
种子随机引擎的一种更好的方法可能是从实现中获得的随机数,而不是使用time.
例如
std::random_device rd;
std::default_random_engine e( rd() );
Run Code Online (Sandbox Code Playgroud)
统一和简化已经提供的一些样本我将总结:
// Good random seed, good engine
auto rnd1 = std::mt19937(std::random_device{}());
// Good random seed, default engine
auto rnd2 = std::default_random_engine(std::random_device{}());
// like rnd1, but force distribution to int32_t range
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));
// like rnd3, but force distribution across negative numbers as well
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));
Run Code Online (Sandbox Code Playgroud)
然后我运行了一些测试来查看默认值是什么样的:
#include <random>
#include <functional>
#include <limits>
#include <iostream>
template<class Func>
void print_min_mean_max(Func f) {
typedef decltype(f()) ret_t;
ret_t min = std::numeric_limits<ret_t>::max(), max = std::numeric_limits<ret_t>::min();
uint64_t total = 0, count = 10000000;
for (uint64_t i = 0; i < count; ++i) {
auto res = f();
min = std::min(min,res);
max = std::max(max,res);
total += res;
}
std::cout << "min: " << min << " mean: " << (total/count) << " max: " << max << std::endl;
}
int main() {
auto rnd1 = std::mt19937(std::random_device{}());
auto rnd2 = std::default_random_engine(std::random_device{}());
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));
print_min_mean_max(rnd1);
print_min_mean_max(rnd2);
print_min_mean_max(rnd3);
print_min_mean_max(rnd4);
}
Run Code Online (Sandbox Code Playgroud)
产生输出:
min: 234 mean: 2147328297 max: 4294966759
min: 349 mean: 1073305503 max: 2147483423
min: 601 mean: 1073779123 max: 2147483022
min: -2147481965 mean: 178496 max: 2147482978
Run Code Online (Sandbox Code Playgroud)
我们可以看到,mt19937和default_random_engine具有不同的默认范围,因此建议使用uniform_int_distribution.
此外,默认的uniform_int_distribution是[0,max_int](非负),即使使用有符号整数类型也是如此.如果您想要全范围,必须明确提供范围.