rand()和srand()函数在c ++中

时间:2016-05-12 19:27:22

标签: c++

我最近一直在学习如何用初学者书编写c ++游戏,我上了一堂课,我必须在这里制作一个游戏,我必须猜测计算机随机选择的数字,我有使用这行代码:

BLAS := atlas

我显然使用iostream cstdlib和ctime。我真的不明白它是如何工作的。它如何选择时间和日期,以及通过什么规则将其转换为unsigned int。基本上,这些功能如何工作。 谢谢!

2 个答案:

答案 0 :(得分:7)

1。关于time()

time(或C ++中更好的std::time)是一个返回某个整数或浮点数的函数,它以某种方式表示当前时间。

它实际返回的算术类型以及它如何表示当前时间是未指定的,但是,最常见的是你将得到一些整数类型,它保存自Unix纪元开始以来的秒数。

2。关于srand()

srand是一个使用其参数(类型为unsigned int)的函数,即所谓的种子,用于设置伪数生成器的内部状态{ {1}}。当我在本答案的其余部分写下 random 时,请阅读伪随机

使用不同的种子通常会导致后续调用rand产生不同的随机数序列,而再次使用相同的种子将导致完全相同的随机数序列。

3。使用rand种子time()

如果我们不希望每次运行程序时都获得相同的随机数,我们需要在每次运行时使用不同的种子。当前时间是这种种子的一种广泛使用的来源,因为它不断变化。

此整数(或其他任何rand()返回的)表示当前时间现在已转换为time并带有unsigned int。实际上并不需要这种显式强制转换,因为所有算术类型都隐式转换为static_cast,但强制转换可能会使某些警告静音。随着时间的推移,我们可以预期结果unsigned int,从而unsigned int产生的随机数序列会发生变化。

4。陷阱

如果常见的话,rand返回自Unix纪元开始以来的秒数,有三个重要的事项要注意:

  1. 只有在两次调用之间至少经过一秒钟时,您生成的序列才会有所不同。
  2. 根据实际实现,如果用于种子time的时间点彼此接近(与自Epoch以来的时间相比),则得到的序列可以开始类似。 Afaik,这是MSVC实施的情况。 如果这是有问题的,只需丢弃序列的前几百或一千个值。(正如我现在所知,这对于{{1}常用的不良RNG并没有多大帮助。如果这有问题,请使用rand,如下所述。)
  3. 你的数字最终不是很随意:如果有人知道你rand的电话是什么时候发生的,他可以从那里得到整个随机数序列。这实际上导致了一个赎金软件的解密工具,使用<random>生成其随机的&#34;加密密钥。
  4. 此外,srand生成的序列往往具有较差的统计特性,即使种子是好的。对于像你这样的玩具程序,这可能很好,但是,对于现实世界的使用,人们应该意识到这一点。

    5。新的srand(time(0))

    C ++ 11引入了新的随机数设施,这些设施在许多方面优于旧的基于rand的东西。它们在标准标题<random>中提供。它包括std::random_device,它提供了获取实际随机种子的方法,强大的伪随机数生成器(如std::mt19937)以及将生成的随机序列映射到整数或浮点范围而不会引入不必要的偏差的工具。

    以下是如何在C ++ 11中随机滚动骰子的示例:

    <random>

    (来自cppr的代码)注意: rand与MinGW无法正常工作,至少在我测试的版本(Nuwen MinGW5.3)中有效!

    还应该注意,#include <random> #include <iostream> int main() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(1, 6); for (int n=0; n<10; ++n) std::cout << dis(gen) << ' '; std::cout << '\n'; } 的状态空间远大于我们(通常)从std::random_device的单个调用中得到的32位。同样,这很可能对玩具程序和家庭作业无关紧要,但作为参考:Here是我尝试正确播种整个州空间,以及答案中的一些有用建议。

    如果您对mt19937 vs random_device的更多详情感兴趣,this是一个有趣的手表。

答案 1 :(得分:0)

第一行: srand()是一个伪随机数生成器。在您的情况下,它会使用系统上的当前时间(执行时间)进行初始化。 第二行: 配置伪随机数生成器后,您可以通过调用rand()来检索随机数。