新的C ++ 11标准有一整章专门用于随机数生成器。但是,我如何执行过去像这样编码的最简单,最常见的任务,但不使用标准C库:
srand((unsigned int)time(0)); int i = rand();
是否可以使用开箱即用的随机数引擎,发行版和种子的合理默认值?
答案 0 :(得分:30)
您应该可以执行以下操作:
std::default_random_engine e((unsigned int)time(0));
int i = e();
default_random_engine
的质量取决于实施方式。您还可以使用std::min_rand0
或std::min_rand
。
种子随机引擎的一种更好的方法可能是实现一个随机数,而不是使用time
。
E.g。
std::random_device rd;
std::default_random_engine e( rd() );
答案 1 :(得分:6)
统一并简化已提供的一些样本,我将总结为:
// 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{}()));
然后我运行了一些测试来查看默认设置:
#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);
}
产生输出:
min: 234 mean: 2147328297 max: 4294966759
min: 349 mean: 1073305503 max: 2147483423
min: 601 mean: 1073779123 max: 2147483022
min: -2147481965 mean: 178496 max: 2147482978
正如我们所看到的,mt19937和default_random_engine具有不同的默认范围,因此建议使用uniform_int_distribution。
此外,默认的uniform_int_distribution是[0,max_int](非负),即使使用有符号整数类型也是如此。如果您想要全范围,必须明确提供范围。
最后,its important to remember this有时会这样。
答案 2 :(得分:2)
如果您的现有代码在新标准之前是合适的,那么它将继续存在。新的随机数发生器被添加用于需要更高质量的伪随机性的应用,例如,随机模拟。
答案 3 :(得分:2)
我在项目中使用以下代码。 '引擎'和'发行'可以是图书馆提供的。
#include <random>
#include <functional>
#include <iostream>
...
std::uniform_int_distribution<unsigned int> unif;
std::random_device rd;
std::mt19937 engine(rd());
std::function<unsigned int()> rnd = std::bind(unif, engine);
std::cout << rnd() << '\n';
答案 4 :(得分:2)
你走了。随机双打范围:
// For ints
// replace _real_ with _int_,
// <double> with <int> and use integer constants
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::default_random_engine rng(std::random_device{}());
std::uniform_real_distribution<double> dist(-100, 100); //(min, max)
//get one
const double random_num = dist(rng);
//or..
//print 10 of them, for fun.
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);} );
return 0;
}
答案 5 :(得分:0)
随机数生成是一个难题。没有真正随机的方法来做到这一点。如果你只是为游戏环境提供随机性,那么你的方法应该没问题。 rand()有几个缺点。
如果您需要随机生成加密密钥,那么您就是S.O.L.在这种情况下,最好的方法是转到通常具有机制的操作系统。在POSIX上,它是随机的()(如果你这么处理,则从/ dev / random读取)。在Windows上,您可以使用CryptoAPI:
答案 6 :(得分:0)
您可以使用RC4生成随机字节。这可能具有您想要的属性。它实现起来快速且相当简单。当种子已知时,序列在所有实现中是可重复的,并且当种子未知时完全不可预测。 http://en.wikipedia.org/wiki/RC4