编程语言
首页 > 编程语言> > C++生成随机数

C++生成随机数

作者:互联网

随机数通过 随机数引擎类随机数分布类

引擎类可以生成 unsigned(无符号数) 随机数序列;分布类使用一个引擎类生成指定类型的、在给定范围内的、服从特定概率分布的随机数。

它们定义在头文件 random 中。

随机数引擎:

随机数引擎是函数对象类,它们定义了一个调用运算符,该运算符不接受参数并 返回一个随机 unsigned 整数。

上代码:

	default_random_engine e;//生成随机无符号数(原始随机数)
	int i = 100;
	for (int  i = 0; i < 10; i++)
	{
		cout << e( ) << endl;//调用对象 e 来生成10个随机数
	}

上面程序输出 :

 以下《C++ primer 》 :

分布类型:

uniform_int_distribution<unsigned> u(1, 100);//生成1到100(包含100)之间的均匀分布的随机数
	default_random_engine e;//生成随机无符号数(原始随机数)
	for (int  i = 0; i < 100; i++)
	{
		cout << u(e) << endl;//将 u 作为随机数源
	}

分布类型也是函数对象类。它接受一个随机数引擎作为参数。

我们传递给分布对象的是引擎对象本身。不能写成 : u ( e() ).

随机数发生器就是指分布对象和引擎对象的组合。

	cout << e.min() << "     " << e.max() << endl;//获得随机数引擎的范围

我们上面所写的代码生成一次随机数,第二次再生成就会是相同的,这并不能达到我们想的真正的随机数。

我们可以把引擎和分布对象定义为 static 的,让它保持状态:


#include <iostream>
#include<random>
using namespace std;
#include<vector>
static default_random_engine e;
static uniform_int_distribution<unsigned> u(1, 100);
vector<unsigned> doo()
{
	vector<unsigned> ret;
	for (int  i = 0; i < 10; i++)
	{
		ret.push_back(u(e));//向容器中添加元素
	}
	for (auto i : ret)//利用范围 for 输出
	{
		cout << i<<"       ";
	}
	return ret;
}
int main() {
	doo(); //13       3       35       86       5       92       30       86       99       4
	cout << endl;
	doo();  //36       66       41       27       40       21       20       5       98       7
	cout << '\n';
	doo();//	10       10       44       40       47       27       37       54       61       72
	system("pause");
	return 0;
}

一个给定的随机数发生器一直会生成相同的随机数序列。我们可以通过设置随机数发生器种子来实现真正的随机数。

每次运行程序都会生成不同的随机结果,我们可以通过提供一个种子来达到目的。

为引擎设置种子的两种方式:在创建引擎对象 时提供种子,或者调用引擎的 seed 成员。

 default_random_engine e1;//使用默认种子值
 default_random_engine e2(32767);//给定种子值
 default_random_engine e3;
 for (int  i = 0; i < 10; i++)
 {
	 cout << e1() <<"   ";
 }
 cout << endl;
 for (int i = 0; i < 10; i++)
 {
	 cout << e2() << "   ";
 }
 cout << endl;
 e3.seed(32767);//调用 seed 设置一个新种子值
 for (int i = 0; i < 10; i++)
 {
	 cout << e3() << "    ";
 }

上面代码中本来 e1 和 e3 都是使用默认的种子值,它们两个生成的随机数序列将会是相同的。e2是我们自己给定的,它和 e1 和 e3 和种子值不同,因些 e2 生成的随机数序列不会是其他两个是一样的。后面我们通过调用 seed 函数为 e3 重新设置了一个种子值,和 e2的一样,又变成了 e2 和 e3 是生成相同的随机数序列。

选择一个好种子是极其困难的: 最常用的方法就是调用系统函数 time , 这个函数定义在头文件 ctime 中,它返回一个特定时刻到当前经过了多少秒。

 default_random_engine e2(time(0));//给定种子值
 uniform_int_distribution<int> u(0, 100);
 cout << endl;
 for (int i = 0; i < 10; i++)
 {
	 cout <<u(e2) << "   ";//第次调用的结果几乎都会不一样
 }

time返回以秒计的时间,因此这种方式只适用于生成种子的间隔为秒级或更长的时间。

生成随机浮点数:

我们定义一个  uniform_real_distribution 类型的对象,让标准库来处理从随机数到随机浮点数的映射。

 default_random_engine e2(time(0));//给定种子值
 uniform_real_distribution<float> u(0, 1);
 for (int i = 0; i < 10; i++)
 {
	 cout <<u(e2) << "   ";//每次调用都会不同的浮点数
 }

分布类型的操作:

 分布类型都是模板,具有单一的模板类型参数,每个分布模板都有一个默认模板实参。

 uniform_real_distribution < > u1(0, 1); //空尖表示我们想使用默认结果类型,默认生成 double 值
 uniform_int_distribution <> u2(0, 100); // 默认生成 unsigned 值

生成非均匀分布的随机数:

normal_distribution 生成浮点值。

default_random_engine e2(time(0));//给定种子值
 normal_distribution<> n(10, 1.3);
 for (int i = 0; i < 10; i++)
 {
	 cout <<lround(n(e2)) << "   ";//lround 函数浮点数舍入到最接近的整数。它定义在头文件cmath中 
 }

bernoulli_distribution类:

它是一个普通类,不接受模板参数。它总是返回一个 bool 值,它返回 true 的概率是一个常数,默认为 0.5;

default_random_engine e2(time(0));//给定种子值
 bernoulli_distribution b;
 for (int i = 0; i < 10; i++)
 {
	 cout <<b(e2) << "   ";//它返回的真假的次数是相同的,因为默认的概率是一样的
 }

使用它的原因是允许我们调整随机的概率:

bernoulli_distribution b; //默认是 50/50 的机会
bernoulli_distribution b(.55);//代表程序有55/45机会

引擎返回相同的随机数序列,所以我们必须要循环外声明引擎对象。不然第次循环都会创建一个新引擎,从而每次都会生成相同的值,分布对象在要保持状态,也应该在循环外面。

其他的扩展感兴趣可以自己看看(来自书《C++ primer》):

 

 

 

标签:int,random,C++,生成,引擎,随机数,distribution
来源: https://blog.csdn.net/m0_57035799/article/details/120789427