C++ 随机数

随机数

程序通常需要一个随机数源。在新标准出现以前,C和C++都依赖rand函数用来生成随机数。

此函数生成均匀分布的伪随机数,范围在0到一个系统相关的最大值(至少为32767)之间。

rand函数存在一些问题,比如不同范围的随机数、随机浮点数、非均匀分布的数等。

随机数库

定义在头文件<random>中的随机数库通过随机数引擎类(random-number engines)随机数分布类(random-number distribution)来解决这些问题。

作用
引擎类生成随机unsigned整数序列
分布类使用引擎返回服从特定概率分布的随机数

随机数库的使用

#include <random>
#include <ctime>
void test1()
{
    default_random_engine e(static_cast<unsigned>(time(nullptr)));//默认随机数引擎,且以当前时间为种子
	cout << "e.min() = " << e.min() << endl;
	cout << "e.max() = " << e.max() << endl;
	uniform_int_distribution<unsigned> u(0, 100);//整型均匀分布,且范围在0~100
	cout << "整型均匀分布:0~100" << endl;
	for (int i = 0;i < 10;++i) {
		cout << u(e) << ends;
	}
	cout << "\n浮点型均匀分布:0~1" << endl;
	uniform_real_distribution<double> ur(0, 1);//浮点型均匀分布,且范围在0~1
	for (int i = 0;i < 10;++i) {
		cout << ur(e) << ends;
	}
}

输出 :

e.min() = 0
e.max() = 4294967295
整型均匀分布:0~100
26 18 81 77 31 58 74 30 90 15
浮点型均匀分布:0~1
0.602874 0.749888 0.406369 0.3374 0.066278 0.378081 0.61525 0.0979531 0.709755 0.608517

默认随机数引擎会生成无符号随机整数,其范围在此为(0,4294967295)。

为了避免每次生成的数都是一样的,需要设置随机种子。

标准库定义了多个随机数引擎类,区别在于性能和随机性质量不同。有关操作见下表:

解释
Engine e;默认构造,使用默认种子
Engine e(s);使用整型值s作为种子
e.seed(s)使用种子s重置引擎的状态
e.min()和e.max()此引擎可生成的最小值和最大值
Engine::result_type此引擎生成的结果类型
e.discard(u)将引擎推进u步,u的类型为unsigned long long

其他分布类型

除了均匀分布以外,还有其他分布类型。

正态分布

#include <cmath>
void test2()
{
	default_random_engine e(static_cast<unsigned>(time(nullptr)));
	normal_distribution<> n(4, 1.5);//正态分布n,均值为4,标准差为1.5
	vector<unsigned> vec(9);//9个0
	for (int i = 0;i < 200;++i) {
		unsigned v = lround(n(e));//此处数学描述应为:n(e)服从正态分布N(4,2.25)。
		if (v < vec.size()) {
			++vec[v];
		}
	}
	for (int i = 0;i < vec.size();++i) {
		cout << i << ":" << string(vec[i], '*') << endl;
	}
}

结果:
正态分布
在程序中,使用了正态分布,其均值为4,标准差为1.5,方差为2.25。
由于normal_distribution<>生成浮点值,所以使用lround函数四舍五入得到整数。
生成200个随机数,它们以均值4位中心,标准差为1.5。由于是正态分布,我们期望生成的数中99%都在0~8之间。
并且使用一个vector将其下标对应数字出现的次数记录下来。之后对结果打印。

伯努利分布

void test3()
{
	default_random_engine e(static_cast<unsigned>(time(nullptr)));
	bernoulli_distribution b(0.6);//普通类,而非模板类
	vector<unsigned> vec(2);
	for (int i = 0;i < 1000;++i) {
		++vec[b(e)];
	}
	cout << "0 出现次数:" << vec[0] << endl;
	cout << "1 出现次数:" << vec[1] << endl;
}

结果:

0 出现次数:405
1 出现次数:595

伯努利分布会随机生成0或1。bernoulli_distribution默认概率为50:50,参数0.6表示其产生1的概率为0.6。

参考资料

《C++ Primer 第5版》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值