Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C srand()—;为什么只叫一次?_C_Random_Srand - Fatal编程技术网

C srand()—;为什么只叫一次?

C srand()—;为什么只叫一次?,c,random,srand,C,Random,Srand,这个问题是关于这个问题中的一个评论 第一条注释指出,在应用程序中只应调用一次srand()。为什么会这样?原因是srand()设置了随机生成器的初始状态,并且生成器生成的所有值只有在您自己不接触状态的情况下才是“足够随机的” 例如,您可以执行以下操作: int getRandomValue() { srand(time(0)); return rand(); } 然后,如果您重复调用该函数,以便time()在相邻调用中返回相同的值,那么您只会得到相同的生成值-这是出于设计。这取

这个问题是关于这个问题中的一个评论
第一条注释指出,在应用程序中只应调用一次
srand()
。为什么会这样?

原因是
srand()
设置了随机生成器的初始状态,并且生成器生成的所有值只有在您自己不接触状态的情况下才是“足够随机的”

例如,您可以执行以下操作:

int getRandomValue()
{
    srand(time(0));
    return rand();
}

然后,如果您重复调用该函数,以便
time()
在相邻调用中返回相同的值,那么您只会得到相同的生成值-这是出于设计。

这取决于您试图实现的目标

随机化作为具有起始值的函数执行,即种子

因此,对于同一种子,您将始终获得相同的值序列

如果每次需要随机值时都尝试设置种子,并且种子是相同的数字,则始终会得到相同的“随机”值

种子通常取自当前时间,即秒,如
时间(NULL)
,因此如果您总是在获取随机数之前设置种子,那么只要您在同一秒内多次调用srand/rand组合,您就会得到相同的数

为了避免此问题,每个应用程序只设置一次srand,因为怀疑两个应用程序实例是否会在同一秒内初始化,因此每个实例将具有不同的随机数序列

但是,有一种轻微的可能性,就是你会在一秒钟内多次运行你的应用程序(特别是如果它是一个短的应用程序,或者是一个命令行工具或类似的东西),那么你将不得不求助于其他一些方法来选择种子(除非你可以在不同的应用程序实例中使用相同的序列)。但正如我所说,这取决于应用程序的使用上下文

此外,您可能希望尝试将精度提高到微秒(将相同种子的可能性降至最低),需要(
sys/time.h
):


sr和种子的伪随机数发生器。如果您多次呼叫,您将重新设置RNG的种子。如果用相同的参数调用它,它将重新启动相同的序列

为了证明这一点,如果你做一些简单的事情,比如:

#include <cstdlib>
#include <cstdio>
int main() {
for(int i = 0; i != 100; ++i) {
        srand(0);
        printf("%d\n", rand());
    }
}
#包括
#包括
int main(){
对于(int i=0;i!=100;++i){
srand(0);
printf(“%d\n”,rand());
}
}

您将看到相同的数字打印100次。

随机数实际上是伪随机数。首先设置一个种子,每次调用
rand
都从中获取一个随机数,并修改内部状态,然后在下一次
rand
调用中使用这个新状态来获取另一个数字。由于使用了特定的公式来生成这些“随机数”,因此在每次调用
rand
后设置特定的种子值将从调用中返回相同的数字。例如
srand(1234);兰德()将返回相同的值。一旦使用种子值初始化初始状态,将生成足够多的随机数,因为您没有使用
srand
设置内部状态,因此这些数字更可能是随机的

通常,我们在初始化种子值时使用
time(NULL)
返回的秒数值。说出
srand(time(NULL))处于循环中。然后循环可以在一秒钟内迭代多次,因此循环在循环中的第二次
rand
调用中循环在循环内迭代的次数将返回相同的“随机数”,这是不需要的。在程序启动时初始化它一次将设置种子一次,并且每次调用
rand
时,都会生成一个新的号码并修改内部状态,因此下一次调用
rand
时会返回一个足够随机的号码

例如,此代码来自:

内部状态
next
被声明为全局状态。每次
myrand
调用都会修改内部状态并进行更新,并返回一个随机数。
myrand
的每次调用都会有不同的
next
值,因此该方法每次调用都会返回不同的数字

查看
mysrand
实现;它只设置传递给
下一个
的种子值。因此,如果在每次调用
rand
之前都将
next
值设置为相同的值,那么它将返回相同的随机值,因为应用在该值上的公式相同,这是不可取的,因为函数被设置为随机的


但是根据您的需要,您可以将seed设置为某个特定值,以便在每次运行时生成相同的“随机序列”,例如对于某些基准测试或其他测试。

使用
srand()
为在同一秒运行的应用程序实例生成不同的seed的更简单解决方案如图所示

srand(time(NULL)-getpid());

此方法使种子非常接近随机,因为无法猜测线程何时开始,pid也将不同。

简短回答:调用
srand()
与随机数生成器的“掷骰子”不同。这也不像洗一副牌。如果有什么不同的话,那更像是剪一副牌

这样想吧
rand()
从一大副牌中进行交易,每次你调用它时,它所做的就是从牌组顶部选择下一张牌,给你值,然后将该牌返回到牌组底部。(是的,这意味着“随机”序列将在一段时间后重复。不过这是一个非常大的牌组:通常是4294967296张牌。)

此外,每次程序运行时,都会从游戏商店购买一组全新的卡,并且每一组全新的卡始终具有相同的顺序。因此,除非您做一些特殊的操作,否则每次程序运行时,它都会从
rand()
返回完全相同的“随机”数

现在,y
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;
}
srand(time(NULL)-getpid());