C/C++如何实现随机数

一、引言
学习 C 语言已经很久了,工作之后便投入了 C++ 的怀抱。一直也没有遇到过随机数的问题,最近工作刚好遇到了,这里也好奇了下,C 语言有 rand 函数来实现随机数,那么 C++ 呢?

二、C++并未对随机数作专门的处理
通过翻阅了 C++ 在线手册,我很遗憾的发现,C++ 并未对随机数的相关函数进行专门的封装,而是直接调用了 头文件作为对于 C 语言的兼容。那么其实在这里,C 和 C++ 都是使用了同样的函数同样的方法来实现随机数的。

std::rand()
定义于 头文件中

int rand();
返回一个范围在 0 到 RAND_MAX 之间的均匀分布的伪随机数

这里第一个函数,std::rand(),用来取 0 到 RAND_MAX 之间均匀分布的伪随机数。什么叫做伪随机数呢?

要知道一点,计算机模拟现实生活中的真正的随机是非常困难的。我们需要一个种子数值,这个种子数值就是用来推导随机数的种子数,那么只要种子数值不变,其实我们每次第一次运行函数 std::rand()获取到的随机数就是一样的。

那么我们如何来获取到真正意义上的随机数呢?

std::rand()
定义于 头文件中

void srand(unsinged seed);
初始化内置的随机数发生器,用于生成值与种子值

引用内容其实已经讲述的非常清楚了,std::srand() 函数就是用来设置 std::rand() 函数的种子数值的。

也就是说,我们只要每次获取随机数之前,调用 std::srand() 函数来设置一个每次都不一样的种子数值,就能保证再调用 std::rand() 函数时能取到不一样的随机数。

那么怎么方便的传入一个每次都不一样的种子数值呢?

std::time()
定义于 头文件

time_t time(std::time_t *time);
返回一个 std::time_t 时间对象,其中 std::time_t 是用来表示时间的运算类型,这个类型的值几乎总是用来表示自 1970 年 1 月 1日以来所经过的秒数的整数类型。

这里,需要解释下 std::time_t 类型,这个值用来表示从很久远之前一个约定俗成的时间点到现在经历过的秒数(记住这个特殊的时间吧 1970 年 1 月 1 日,有人说是 Unix 系统的时间纪元,也有人说是 C 语言诞生的日子)。

其中,向 std::time() 函数传入 NULL 空值,就能够得到表示当前时间的std::time_t 对象,这个值是一个从 1970 年 1 月 1 日到现在经历过的秒数的整型值,可以保证每次调用都是不一样的,因此可以用来作为 std::srand() 函数的参数作为种子数值来获取随机数使用。

话说了这么多,还是上一个 C++ 参考手册的示例代码吧:

#include <cstdlib>
#include <iostream>
#include <ctime>

int main()
{
    // use current time as seed for random generator
    std::srand(std::time(0));
    int uniform_random_variable = std::rand();
    std::cout << "Uniform random value on [0" << RAND_MAX << "]: "
    << uniform_random_variable << "\n";
}

如此这般,我们就得到了一个每次运行程序都不一样的随机数。

三、要获取指定范围内的随机数怎么办
看到这里,或许你有点疑惑了。怎么获取指定范围内的随机数呢?

我们看到上面的例子中,我们获取到的随机数范围在 [0, RAND_MAX] 之中,那么我们如何将 [0, RAND_MAX] 的范围缩放到我们想要的范围呢?

使用 % 取余运算。

答案很简单,我们如果想要获取 [0, 10] 的范围,代码该怎么写呢:

#include <cstdlib>
#include <iostream>
#include <ctime>

int main()
{
    // use current time as seed for random generator
    std::srand(std::time(0));
    int uniform_random_variable = std::rand() % 11;
    std::cout << "Uniform random value on [0" << RAND_MAX << "]: "
    << uniform_random_variable << "\n";
}

仔细看代码,哪里修改了呢?

其实就在 std::rand() 函数后面添加了一个 % 11,请注意了,这里是取的 11 的余,为什么是 11 呢?

因为 [0, 10] 的范围,其实是有 11 个数字,那么怎么能够保证这 11 个数字能够被取余到呢?肯定得取 11 的余了。

四、总结
以上讨论了很多,其实 C/C++ 实现随机数是非常简单的:

首先,使用 std::time() 函数取得一个每次都不一样的时间作为种子数值

然后,使用 std::srand() 函数设置这个种子数值初始化随机数发生器

最后,我们使用 std::rand() 函数根据我们所需要缩放的范围进行取余处理制造我们所需要的随机数

怎么样,按照我这样整理和介绍之后,实现随机数是不是没有那么难以理解了呢?

最后,不得不说 C++在线手册 真的非常强大,有事没事多翻翻多查查多看看,真的能够学到不少东西。

猜你喜欢

转载自blog.csdn.net/qq_36946274/article/details/80793389