您的位置:

C++ Random:生成随机数的全能利器

一、概述

C++中的random库提供了一种方便的生成随机数的方法。随机数可以应用于很多领域,比如博弈、密码学、计算机图形学等。C++ Random的优势主要在于其灵活性和高效性。Random库允许用户控制生成的随机数范围、分布和种子,从而满足不同领域的需求。下面将从多个方面对Random库进行详细的阐述。

二、Random库使用方法

C++ Random库是C++11标准引入的新特性,它提供了各种产生随机数的方法。这里我们介绍一下最基本的生成随机整数和浮点数的方法。

1. 生成随机整数

#include 
#include 
   
using namespace std;

int main()
{
    // 默认构造函数使用随机设备为种子生成随机数
    default_random_engine random(time(NULL));
    uniform_int_distribution
     uid(0, 9);
    for (int i = 0; i < 10; i++)
    {
        int num = uid(random);
        cout << num << endl;
    }
    return 0;
}

    
   
  

代码解释:

首先我们使用默认构造函数构造随机设备,将当前时间做为种子生成随机数。Uniform_int_distribution用来定义生成随机整数的范围为0~9。随后在循环中不断调用uid和random来获取随机整数。这样我们就可以得到一个随机整数的序列。

2. 生成随机浮点数

生成随机浮点数就需要使用uniform_real_distribution类了,代码如下:

#include 
#include 
   
using namespace std;

int main()
{
    default_random_engine random(time(NULL));
    uniform_real_distribution
     uid(0.0, 1.0);
    for (int i = 0; i < 10; i++)
    {
        float num = uid(random);
        cout << num << endl;
    }
    return 0;
}

    
   
  

代码解释:

这段代码与生成随机整数的代码很相似。唯一不同的地方是我们使用了uniform_real_distribution类来生成随机浮点数。同样的,我们可以使用random和uid来获取浮点数的序列。

三、Random库进阶应用

1. 控制种子

在Random库中,我们可以通过改变随机数生成器的种子来控制随机序列的生成。Seed_seq是一个用来生成随机数种子序列的类,并可以控制随机数序列的生成。下面是一个关于控制种子的例子:

#include 
#include 
   
using namespace std;

int main()
{
    int seed[3] = {1, 2, 3};
    seed_seq sseq(seed, seed + 3);
    mt19937 gen(sseq);
    uniform_int_distribution
     uid(0, 10);
    for (int i = 0; i < 10; i++)
    {
        int num = uid(gen);
        cout << num << endl;
    }
    return 0;
}

    
   
  

代码解释:

首先我们定义一个长度为3的int数组seed,并将其作为参数传给seed_seq类。seed_seq类的构造函数将seed数组中的值转化为均匀分布在32位整数空间内的随机数种子序列,并将其存储在一定的缓存中。用户可以通过传递缓存来控制自己的随机数生成序列。由于mt19937引擎和默认引擎一样,也接受整数种子,所以我们直接将随机数种子序列传递给mt19937对象,并使用uid随机分布来随机数,输出结果。

2. 修改随机数分布

Random库的随机数分布类有:uniform_int_distribution、uniform_real_distribution、normal_distribution、chi_squared_distribution、cauchy_distribution和gamma_distribution等。不同的分布定义了不同的随机数生成规律。下面是一个改变随机分布的例子:

#include 
#include 
   
using namespace std;

int main()
{
    default_random_engine random(time(NULL));
    normal_distribution
     nd(5.0, 1.5);
    for (int i = 0; i < 10; i++)
    {
        double num = nd(random);
        cout << num << endl;
    }
    return 0;
}

    
   
  

代码解释:

这段代码与前面的随机整数和浮点数的生成代码非常相似。这个例子中我们使用normal_distribution来定义正态分布,其参数分别为均值和标准差。均值越大,所得到的随机数分布中心越靠后,而标准差越大,则随机数分布的幅度越宽广。

3. 生成随机数类

如果我们需要在大量代码中使用随机数,每次都写一遍随机数生成代码可能会比较冗余。实际上,Random库提供了一个方便的生成随机数类,可以简化我们的代码量。下面是一个使用生成随机数类的例子:

#include 
#include 
   
using namespace std;

class RandomNumberGenerator
{
private:
    mt19937 generator;

public:
    RandomNumberGenerator()
    {
        std::random_device rd;
        generator.seed(rd());
    }

    int getRandomInt(int min, int max)
    {
        std::uniform_int_distribution
     dist(min, max);
        return dist(generator);
    }

    float getRandomFloat(float min, float max)
    {
        std::uniform_real_distribution
      dist(min, max);
        return dist(generator);
    }
};

int main()
{
    RandomNumberGenerator rng;
    for (int i = 0; i < 10; i++)
    {
        int num = rng.getRandomInt(0, 10);
        float fnum = rng.getRandomFloat(0.0, 1.0);
        cout << num << "," << fnum << endl;
    }
    return 0;
}

     
    
   
  

代码解释:

这个例子中,我们定义了RandomNumberGenerator类,通过类的实例化来使用随机数生成器。类构造函数中我们使用std::random_device产生随机设备,而不是用当前时间做为种子。RandomNumberGenerator类定义了getRandomInt和getRandomFloat成员函数来生成随机整数和随机浮点数。注意到,我们在成员函数中也是用uniform_int_distribution和uniform_real_distribution来定义随机数的范围,使用了函数模板来允许指定不同的类型。

4. 并行生成随机数

为了提高随机数的生成效率,Random库提供了一个并行生成随机数的方法,从而快速生成一定规模的随机数序列。parallel_random_device方法用于生成一个并行随机设备,它保证多线程访问该设备不会互相干扰。下面是一个并行生成随机数的例子:

#include 
#include 
   
#include 
    
using namespace std;

int main()
{
    std::vector
      nums(10000);
    std::independent_bits_engine
       e;
    std::generate(nums.begin(), nums.end(), std::bind(e));
    for (int i = 0; i < 10000; i += 100)
    {
        cout << nums[i] << endl;
        std::this_thread::sleep_for(std::chrono::duration
       
        (100)); } return 0; }
       
      
     
    
   
  

代码解释:

这个例子中我们使用independent_bits_engine方法来生成一个独立的颗粒生成随机数的设备。该函数的模板参数包括:随机数引擎类型、生成的随机数位数、随机数种子类型。我们使用std::default_random_engine作为随机数引擎类型,CHAR_BIT(即8)作为生成随机数的位数,unsigned int作为随机数种子类型。随后我们生成了一个长度为10000的int数组,并使用std::generate方法和std::bind函数来快速生成10,000个随机数。在循环中,我们每次输出数组中的一个元素,并等待100毫秒。

四、总结

总地来讲,C++ Random库提供了各种方便的生成随机数的方法,适用于博弈、密码学、计算机图形学等领域。在使用中需要注意控制随机数生成器的种子、随机数分布和并行生成随机数的使用方法。待需要使用全局共享的随机数生成时,我们可以使用独立随机设备的方式来保证多线程生成的随机数不会互相干扰。通过Random库,C++开发工程师可以轻松生成随机数序列,丰富自己的代码体验。