C++排雷:21.C++生成随机数(rand、srand、random库)

  • C++11之前,没有自带的random函数,要生成随机数,普遍采用rand和srand()。
  • C++11之后,内部提供了强大的随机数库Random。

rand()

其内部实现是用线性同余法做的,生成是可看做一定范围内随机的伪随机数,其最大范围和系统相关。

通用公式:

  • a + rand() % n;其中的a是起始值,n是整数的范围。
  • 或 a+(int)b * rand() / (RAND_MAX + 1)。
  • 要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
	
    for (int i = 0; i < 10; i++)//输出十次
    {
        cout << rand()%100<< " ";//范围在[0,100)的随机数
    }
    return 0;
}

注意:没有随机种子,多次重复运行,产生的随机数结果是相同的。

srand()

srand()可用来设置rand()产生随机数时的随机数种子。

  • 通过设置不同的种子,我们可以获取不同的随机数序列。
  • 例如,使用srand((int)(time(NULL))的方法,利用系统时钟,产生不同的随机数种子。不过要调用time(),需要加入头文件ctime。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand((int)time(0));  // 产生随机种子  把0换成NULL也行
    for (int i = 0; i < 10; i++)//产生十次
    {
        cout << rand()%100<< " ";//范围在[0,100)的随机数
    }
    return 0;
}

插入随机种子后,多次运行代码,随机数的结果不同。
为了方便使用,可以使用宏定义:

#include <iostream>
#include <cstdlib>
#include <ctime>
#define random(x) rand()%(x)
using namespace std;

int main()
{
    srand((int)time(0));  // 产生随机种子  把0换成NULL也行
    for (int i = 0; i < 10; i++)
    {
        cout << random(100) << " ";
    }
    return 0;
}

Random库

包括:

  • 随机数引擎类(random-number engines)
  • 随机数分布类(random-number distribution)
  • 二者一般配合使用。
1.引擎和分布

①随机数引擎类

  • 被称为“原始随机数发生器”,它以均匀的概率生成某一类型的随机数
  • 但无法指定随机数的范围、概率等信息,通常不会被单独使用。

②随机数分布类

  • 需要配合随机数引擎类才能运行
  • 利用随机数引擎生成符合条件的随机数,例如某一区间范围、某一分布概率的随机数。

③随机数类常用的主要有以下四个:

  • default_random_engine:随机非负数(不建议单独使用);
  • uniform_int_distribution:指定范围的随机非负数;
  • uniform_real_distribution:指定范围的随机实数;
  • bernoulli_distribution:指定概率的随机布尔值。
2.参考几个实例:

①default_random_engine

  • 是一个随机数引擎类。
  • 调用运算符无参返回一个随机的 unsigned 类型的值。
#include <iostream>
#include <random>
using namespace std; 
int main( )
{    
default_random_engine e;   // 生成随机无符号数 
for(int i=0; i<10; ++i)        
cout<<e( )<<endl;    // e() “调用”对象来生成下一个随机数
return 0;
}

②uniform_int_distribution

  • 是一个随机数分布类,也是个模板类
  • 模板参数为生成随机数的类型(int、unsigned、short、unsigned short、long、unsigned long、long long、unsigned long long)。
  • 它的构造函数接受两个值,表示随机数的分布范围(闭区间)。
//生成 [0,9]均匀分布的随机数
uniform_int_distribution<unsigned> u(0,9);
default_random_engine e;    // 生成无符号随机整数
for (size_t i =0;i<10; i++)
    // 将 u 作为随机数源
    // 每个调用返回在指定范围内并服从均匀分布的值
    cout<<u(e)<<" ";
cout<< endl;

③uniform_real_distribution

  • 是一个随机数分布类,它也是模板类
  • 参数表示随机数类型(可选类型为 float、double、long double)
#include <iostream>
#include <random>
using namespace std; 
int main( )
{    
	default_random_engine e;    
	uniform_real_distribution<double> u(0.0, 1.0);
	for(int i=0; i<10; ++i)        
	cout<<u(e)<<endl;   
 	return 0;
 }

④bernoulli_distribution

  • 是一个分布类,但它不是模板类。
  • 它的构造函数只有一个参数,表示该类返回 true 的概率,该参数默认为 0.5 ,即返回 true 和 false 的概率相等。
#include <iostream>
#include <random>
using namespace std; 
int main( )
{    
	default_random_engine e;    
	bernoulli_distribution u;    
	for(int i=0; i<10; ++i)        
	cout<<u(e)<<endl;    
	return 0;
}

3.“固定”的随机

随机数发生器在默认情况下,对于一个给定的发生器,每次运行程序它都会返回相同的随机结果。

  • 随机结果不变便于调试,但也不应该忽视这一问题。

通俗讲,就是如果我设置了个函数output_random()输出5个0到9之间的随机数。

  • 每次调用output_random()时,输出的结果是一样的。
  • 这并不满足我希望每次都有新随机的需求

因此应该将他们定义为static 的,从而每次调用都生成新的数:

 static default_random_engine e;
    
    static uniform_int_distribution<unsigned > u(0,9);

或者,在不需要调试确认后,加入随机种子:

default_random_engine e;
 e.seed(13)

或者加个时间种子:

  • default_random_engine e1(time(0));

C++ 11 还规定了可以生成 20 种不同的分布类型,有具体需求时可以参考 C++ Primer 781页或:http://www.cplusplus.com/reference/random/
参考文献1
参考文献2
参考文献3

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值