如何使用c++ 11标准库生成随机数

How do I generate a random number using the C++11 standard library

本文关键字:随机数 标准 何使用 c++      更新时间:2023-10-16

新的c++ 11标准有整整一章专门介绍随机数生成器。但是,我如何执行最简单、最常见的任务,这些任务过去是这样编码的,但不依赖于标准的C库:

<>之前将srand ((unsigned int)时间(0));Int I = rand();

对于随机数引擎、分布和种子是否存在合理的默认值?

您应该能够做如下操作:

std::default_random_engine e((unsigned int)time(0));
int i = e();

default_random_engine的质量取决于实现。您也可以使用std::min_rand0std::min_rand

可能一个更好的方法来播种一个随机引擎是真正的随机数,因为可以从实现,而不是使用time

std::random_device rd;
std::default_random_engine e( rd() );

统一和简化已经提供的一些示例,我将总结为:

// 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](非负),即使使用有符号整数类型也是如此。如果想要全量程,必须显式提供量程。

如果您现有的代码在新标准之前是合适的,那么它将继续适用。新的随机数生成器被添加到需要更高质量的伪随机性的应用程序中,例如随机模拟。

我在我的项目中使用以下代码。'engine'和'distribution'可以是库提供的其中一个。

#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';

给你。范围内的随机双精度:

// 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;
}

随机数生成是一个难题。没有真正随机的方法来做到这一点。如果你只是为了创造一个游戏环境而创造随机性,那么你的方法便是可行的。Rand()有几个缺点。

如果你需要随机生成加密密钥,那么你是s.o.l。在这种情况下,最好的方法是去操作系统,它通常有机制。在POSIX上,它是random()(或者从/dev/random读取,如果你愿意的话)。在Windows上,您可以使用CryptoAPI:

https://www.securecoding.cert.org/confluence/display/seccode/MSC30-C。+ +不+使用+ +兰特% 29 +功能+ 28% +生成+伪随机+数字

您可以使用RC4生成随机字节。这可能有你想要的属性。它是快速和相当简单的实现。当种子已知时,序列在所有实现中都是可重复的,而当种子未知时,序列是完全不可预测的。http://en.wikipedia.org/wiki/RC4