这个问题是关于这个问题的评论
推荐的方法来初始化srand?第一条评论说srand()应该只在应用程序中调用ONCE.为什么会这样?
Kor*_*tak 100
这取决于你想要达到的目标.
随机化是作为具有一个起始值,即函数进行种子.
因此,对于相同的种子,您将始终获得相同的值序列.
如果您在每次需要随机值时尝试设置种子,并且种子是相同的数字,您将始终获得相同的"随机"值.
种子通常取自当前时间,即秒数,time(NULL)因此,如果你总是在取随机数之前设置种子,只要你多次调用srand/rand组合,你就会得到相同的数字.同一秒.
为了避免这个问题,每个应用程序只设置一次srand,因为两个应用程序实例将在同一秒内初始化是值得怀疑的,因此每个实例将具有不同的随机数序列.
但是,您可能会在一秒钟内多次运行您的应用程序(特别是如果它是一个短的应用程序或命令行工具或类似的东西),那么您将不得不采用其他方式选择一个种子(除非你在不同的应用程序实例中使用相同的序列).但就像我说的那,这取决于你的应用程序使用环境.
此外,您可能希望尝试将精度提高到微秒(最小化相同种子的几率),requires(sys/time.h):
struct timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec * t1.tv_sec);
Run Code Online (Sandbox Code Playgroud)
pho*_*xis 23
随机数实际上是伪随机数.首先设置种子,每次调用rand获取一个随机数,并修改内部状态,并在下一次rand调用中使用此新状态以获取另一个数字.因为某个公式用于生成这些"随机数",因此在每次调用之后设置一定数量的种子rand将从调用中返回相同的数字.例如,srand (1234); rand ();将返回相同的值.使用种子值初始化初始状态将生成足够的随机数,因为您没有设置内部状态srand,因此使得数字更可能是随机的.
通常,我们time (NULL)在初始化种子值时使用返回的秒值.说srand (time (NULL));是循环.然后循环可以在一秒内迭代多次,因此循环在循环中的第二次rand调用中循环内循环的次数将返回相同的"随机数",这是不希望的.在程序启动时初始化一次将设置种子一次,并且每次rand调用时,生成一个新数字并修改内部状态,因此下一个调用rand返回一个足够随机的数字.
例如来自http://linux.die.net/man/3/rand的代码:
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
next = seed;
}
Run Code Online (Sandbox Code Playgroud)
内部状态next被声明为全局.每次myrand调用都将修改内部状态并更新它,并返回一个随机数.每次调用myrand将具有不同的next值,因此该方法将在每次调用时返回不同的数字.
看看mysrand实施情况; 它只是设置您传递给的种子值next.因此,如果您next在调用之前每次设置相同的值rand将返回相同的随机值,因为应用了相同的公式,这是不可取的,因为该函数是随机的.
但是根据您的需要,您可以将种子设置为某个特定值,以便在每次运行时生成相同的"随机序列",比如针对某些基准或其他.
简短的回答:通话srand()时不喜欢"掷骰子"随机数发生器.也不像洗牌一样.如果有的话,更像是切割一副牌.
想想这样. rand()从一大堆卡片开始交易,每次你打电话,它所做的就是从牌组顶部挑出下一张牌,给你价值,并将牌返回到牌组的底部.(是的,这意味着"随机"序列会在一段时间后重复出现.但这是一个非常大的套牌:通常是4,294,967,296张牌.)
此外,每一个程序运行时,卡一个全新的包从游戏商店买,和卡每一个全新的包总是具有相同的序列.因此,除非你做一些特殊的事情,否则每次你的程序运行时,都会得到完全相同的"随机"数字rand().
现在,你可能会说,"好吧,那我怎么洗牌?" 答案是(至少就rand和srand关注),没有洗牌甲板的一种方式.
那怎么srand办?基于我在这里建立的类比,打电话srand(n)基本上就像是说" n从顶部切割甲板卡".但是等一下,还有一件事:它实际上需要另一个全新的套牌,并n从顶部切下卡片.
所以,如果你打电话srand(n),rand(),srand(n),rand(),...,用相同的n每一次,你不会只是得到一个不是非常随机序列,你就会得到相同数量的从后rand()每次.(不一定是你递给的号码srand,但rand反复使用相同的号码.)
因此,你可以做的最好的事情就是在你的程序开始时切换一次套牌,也就是说srand(),在你的程序开始时调用一次,n这是合理随机的,这样你就可以在每次你的大牌中从一个不同的随机位置开始程序运行.
[PS是的,我知道,在现实生活中,当你购买一副全新的卡片时,它通常是有序的,而不是随机顺序.对于这里的类比,我想象你从游戏商店购买的每个牌组都是看似随机的顺序,但是与你在同一商店购买的其他牌组完全相同的看似随机的顺序.有点像他们在桥牌锦标赛中使用的相同洗牌的牌组.]
原因是srand()设置随机生成器的初始状态,并且如果您不在其间触摸状态,则生成器生成的所有值仅"足够随机".
例如,您可以这样做:
int getRandomValue()
{
srand(time(0));
return rand();
}
Run Code Online (Sandbox Code Playgroud)
然后,如果你重复调用该函数,以便time()在相邻的调用中返回相同的值,你只需要生成相同的值 - 这是设计的.