C++11 随机数生成

       C++ 程序中,在新标准出现之前,C 和 C++ 都依赖一个C 库函数 rand 来产生随机数,然而,这个函数生成的是均匀分布的伪随机数,每个随机数的范围在 0 和一个最大值RAND_MAX(至少为 32767)之间。

  rand 函数存在一些问题:在实际的编程中,很多程序需要不通范围的随机数。一些应用需要随机浮点数。一些程序需要非均匀分布的随机数。所在在编写程序时为了生成满足一定要求的随机数,通常会转换 rand 生成的随机数的范围、类型或者是分布,但是这样会引入非随机性。

       c++11提供的<random>实现了随机数库,它通过随机数引擎类(random_number_engines)产生随机数序列,随机数分布类(random_number_distribution)使用随机数引擎生成服从特定概率分布的随机数。

下面介绍一个C++中生成随机数的例子:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
//#include "Timer.h"
#include <random>


// const int arraySize = 100000;
int main()
{
	std::default_random_engine e;    // 默认的随机数引擎
	for (int i = 0; i < 15; i++)
	{
		auto rnd = e();
		std::cout << rnd << std::endl;
		std::cout << typeid(rnd).name() << std::endl;   // 返回值的类型
	}
	std::cout << e.max() << " | " << e.min() << std::endl;   // 随机数引擎的范围
	//system("pause");
    return 0;
}

       随机数类是定义在std命名空间的,所以要声明。随机数引擎是函数对象,这就是为什么使用e()去生成随机数。程序每次运行都会生成相同的随机数序列,这在一定程度有利于程序的调试,但我们有时需要每一次运行产生的随机数序列都是不同的。我们可以通过设置随机数引擎的种子来改变引擎的状态,没有改变时是使用默认的随机数种子,这就是为什么每一次都生成同样的随机数序列。从结果我们可以知道,默认的种子生成随机数范围在1-2147483646之间。

可以通过e.seed()方法来设置随机数种子:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
//#include "Timer.h"
#include <random>


// const int arraySize = 100000;
int main()
{
	std::default_random_engine e;    // 默认的随机数引擎
	e.seed(10);    // 设置生成随机数的种子
	for (int i = 0; i < 15; i++)
	{
		auto rnd = e();
		std::cout << rnd << std::endl;
		//std::cout << typeid(rnd).name() << std::endl;   // 返回值的类型
	}
	std::cout << e.max() << " | " << e.min() << std::endl;   // 随机数引擎的范围
	//system("pause");
    return 0;
}

如果需要改变生成的随机数的范围,需要使用随机数分布类:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
//#include "Timer.h"
#include <random>


// const int arraySize = 100000;
int main()
{
	std::default_random_engine e;    // 默认的随机数引擎
	std::uniform_int_distribution<int> u(0, 10);    // 随机数分布类,可以确定随机数范围 [0,10]
	e.seed(10);    // 设置生成随机数的种子
	for (int i = 0; i < 15; i++)
	{
		auto rnd = u(e);
		std::cout << rnd << "  ";
		//std::cout << typeid(rnd).name() << std::endl;   // 返回值的类型
	}
	std::cout << std::endl;
	std::cout << e.max() << " | " << e.min() << std::endl;   // 随机数引擎的范围
	//system("pause");
    return 0;
}

在实际的应用中,[0, 1]之间的随机数应用的比较广泛,在C++11中,可以按照如下的方式生成满足要求的随机数:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
//#include "Timer.h"
#include <random>


// const int arraySize = 100000;
int main()
{
	std::default_random_engine e;    // 默认的随机数引擎
	std::uniform_real_distribution<double> u(0, 1);    // 随机数分布类,可以确定随机数范围 [0,10]
	e.seed(10);    // 设置生成随机数的种子
	for (int i = 0; i < 15; i++)
	{
		auto rnd = u(e);
		std::cout << rnd << "  ";
		//std::cout << typeid(rnd).name() << std::endl;   // 返回值的类型
	}
	std::cout << std::endl;
	std::cout << e.max() << " | " << e.min() << std::endl;   // 随机数引擎的范围
	//system("pause");
    return 0;
}

除此之外,c++11的<random>库还提供了不同的随机数引擎和随机数分布类,例如,要生成满足正态分布的0-1之间的随机数:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include "Timer.h"
#include <random>


// const int arraySize = 100000;
int main()
{
	std::default_random_engine e;    // 默认的随机数引擎
	// std::normal_distribution的构造函数  可知参数的意义
	// explicit normal_distribution(_Ty _Mean0 = 0.0, _Ty _Sigma0 = 1.0)  
	std::normal_distribution<double> u(0, 1);    // 正态分布 
	e.seed(10);    // 设置生成随机数的种子
	for (int i = 0; i < 15; i++)
	{
		auto rnd = u(e);
		std::cout << rnd << "  ";
		//std::cout << typeid(rnd).name() << std::endl;   // 返回值的类型
	}
	std::cout << std::endl;
	std::cout << e.max() << " | " << e.min() << std::endl;   // 随机数引擎的范围
	//system("pause");
    return 0;
}

C++11 提供的随机数引擎和随机数分布类型如下所示:
http://www.cplusplus.com/reference/random/?kw=random

随机数引擎:

随机数分布类:

------------------------------------------------------------------------------------------------------

posted @ 2019-08-10 20:02  Alpha205  阅读(366)  评论(0编辑  收藏  举报