1.关于time()
time
(或更好std::time
在C++)是返回表示以某种方式在当前时间某个整数或浮点数的函数。
它没有指定它实际返回的算术类型以及它如何表示当前时间,但是,最常见的情况是,您将获得一些整数类型,它保存自Unix时代开始以来的秒数。
2.关于srand()
srand
是使用它的参数(这是unsigned int
类型的),即所谓的种子,以设置伪随机数发生器rand
的内部状态的功能。当我在这个答案的其余部分中写随机,请阅读伪随机。
使用不同的种子通常会导致随后调用rand
产生的随机数的不同序列,而再次使用相同的种子将导致完全相同的随机数序列。
3.使用time()
种子rand()
如果我们不希望我们每次运行程序时得到相同的随机数,我们需要一些种子是在每次运行时不同。当前时间是这种种子广泛使用的来源,因为它不断变化。
表示当前时间的此整数(或返回的任何其他time
)现在转换为unsigned int
,其中static_cast
。由于所有算术类型都隐含地转换为unsigned int
,但这种明确的转换并不是实际需要的,但演员可能会默认一些警告。随着时间的推移,我们可以预期产生的unsigned int
以及由rand
产生的随机数序列改变。
4.陷阱
如果像常见,time
返回的秒数,因为Unix纪元的开始,也有需要注意的三个重要的事情:
- 你产生将序列只有在两次调用之间至少经过了一秒时才会有所不同。
- 根据实际实施情况,如果用于种子
rand
的时间点彼此接近(与自Epoch以来的时间相比),则结果序列可能开始具有类似性。 Afaik,这是MSVC实施中的情况。如果这是有问题的,只需丢弃序列的前几百或上千个值即可。(正如我现在所知道的,这对于rand
常用的差RNG并没有多大帮助,所以如果有问题,请使用<random>
,如下所述)。
- 您的号码最后并不是很随意:如果有人知道您何时致电
srand
,他可以从中得出整个随机数序列。这实际上导致了一个使用srand(time(0))
生成其“随机”加密密钥的勒索软件的解密工具。
另外,由rand
产生的序列倾向于具有差的统计特性,即使种子是好的。对于像你这样的玩具程序,这可能很好,但是,对于真实世界的使用,应该意识到这一点。
5.新<random>
C++ 11引入了新的随机数的设施,是优于老rand
基础的东西很多方面。他们在标准标题<random>
中提供。它包括std::random_device
,它提供了一种方法来获得实际上随机的种子,强大的伪随机数发生器,如std::mt19937
以及将产生的随机序列映射到整数或浮点范围而不会引入不必要的偏倚的工具。
下面是一个例子如何随机地滚动在C++ 11的模头:
#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';
}
(代码从cppr)注:std::random_device
不与MinGW的正常工作,至少在版本( Nuwen MinGW5.3)我测试过了!
还应该注意的是,mt19937
的状态空间远大于我们(通常)从单个调用random_device
中跳出的32位。再次,这对玩具程序和家庭作业来说很可能并不重要,但作为参考:Here是我尝试正确地播种整个状态空间,并在答案中加上一些有用的建议。
如果您有兴趣了解关于rand
的更多详情和<random>
,this是一款有趣的手表。
查看'srand'和'rand'的文档。在C++ 11或更高版本中,应该使用http://en.cppreference.com/w/cpp/numeric/random中的类型。 – Kevin
如果你看[time()']的规范(http://en.cppreference.com/w/cpp/chrono/c/time),你会发现它返回一个'time_t'。如果你看看[time_t'的定义](http://en.cppreference.com/w/cpp/chrono/c/time_t),你会发现它几乎总是一个整型。事实上,我不知道它没有的实现。因此没有问题将其转换为常规的“int”。 –
P.S.我不同意这应该作为一个副本来关闭,因为它更多地讨论'时间'和'srand'之间的相互作用,而不是rand/srand本身。 –