为啥 srandom(time(NULL)) 在 main() 函数和用户定义函数中的行为不同?

Posted

技术标签:

【中文标题】为啥 srandom(time(NULL)) 在 main() 函数和用户定义函数中的行为不同?【英文标题】:Why does srandom(time(NULL)) behave differently within main() function and that of a user defined function?为什么 srandom(time(NULL)) 在 main() 函数和用户定义函数中的行为不同? 【发布时间】:2016-03-25 22:44:22 【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void sep_gen(void);

int main()

srandom((unsigned)time(NULL));
printf("Random Numbers\n");

sep_gen();
sep_gen();
sep_gen();

return(0);


void sep_gen(void)

long int r;
int i;

for (i=0;i<10;i++)
    putchar('-');
putchar('\n');

r=random();
printf("%ld\n",r);

上面的代码按预期生成了三个不同的整数。但是,当使用 sep_gen() 函数 srandom((unsigned)time(NULL)) 时,生成的整数三次都相同。 (代码如下)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void sep_gen(void);

int main()

printf("Random Numbers\n");

sep_gen();
sep_gen();
sep_gen();

return(0);


void sep_gen(void)


srandom((unsigned)time(NULL));
long int r;
int i;

for (i=0;i<10;i++)
    putchar('-');
putchar('\n');

r=random();
printf("%ld\n",r);

我的问题是为什么 random() 函数在 srandom() 函数被放置在 main 函数中时会生成不同的数字,但在 sep_gen() 函数中却不这样做?

【问题讨论】:

srandom 不是标准函数。 @Olaf:根据the man page,它是 POSIX.1-2001 的一部分。不知道为什么这很重要。 @ShadowRanger:见How to Ask 以及minimal reproducible example 是什么。有一个适当的标签,例如POSIX,否则应该在文本中。 @Olaf:哇,这太荒谬了。 srandom 并不是一个非常晦涩难懂的函数,期望一个相对较新的用户能够完美地将其称为 POSIX 函数是愚蠢的。 @ShadowRanger:评论是为了澄清并要求在问题中添加相关信息。你知道这也被其他初学者读过,是吗?不能假设每个人都知道 POSIX 函数,并且很可能想知道 randomsrandom 实际做了什么。更重要的是,因为名称在随机数上下文中很明显。你说这样的澄清是很挑剔的。 【参考方案1】:

将其放入sep_gen 意味着您每次调用sep_gen 时都会重新设置种子,而不是每次程序运行一次。并且time 正在返回自纪元以来的秒数;您的程序很可能会在同一秒内全部调用 sep_gen 三次,因此您在每次调用 random 之前都会重新播种到一个固定的起点。

基本上,作为一项规则,一个程序应该只为其随机源播种一次,或者如果它出于某种原因需要重新播种,则需要确保它不使用没有足够变化的种子源。在不重复自己的情况下重新播种的一种非常简单的方法类似于srandom(time(NULL) ^ random());,因此生成器的现有状态会干扰变化不足的外部种子源time()。这只是一个玩具示例(不断干扰time 不会对预期行为做出巨大改变),只是说明如何在更复杂的场景中执行此类操作。

【讨论】:

能否详细说明重新播种的方法? 'srandom(time(NULL)^random());' 如何工作?另外,当您说它不会对预期行为做出巨大改变时,您是什么意思?抱歉,我是初学者,所以我没有遵循这部分。 @ArshithaBasavaraj:它调用random 从现有的随机流和按位异或与time 中提取一个值。所以种子有两个“随机性”来源,最后一次播种的内容是什么,从那时起随机抽取了多少次(尽管在这种情况下,每次都重新播种),加上time 输出。按位异或意味着这两个值会切换对方的位,组合起来很有用。它不会对行为有太大的改变,因为大多数时候,random 流是可以预测的;如果您知道程序启动的时间,您可以重现随机流。【参考方案2】:

这是由于您的代码处理速度很快。 srandom 所做的是重置随机数生成器的种子。如果你在一个函数中调用它,它会在你调用一个函数的任何时候更新为当前时间。计算速度非常快,每次调用都检索到相同的时间,因此生成的数字与给定种子的序列的第一个数字相同。

【讨论】:

它只被调用一次,因此种子不会重置为相同的值。 把它想象成用0初始化连续整数的序列。如果你初始化一次你会得到0、1、2、3等等。如果您每次将其重置为 0,您将获得 0, 0, 0... 当它在主函数中时会如何改变? (对不起,我重复了我的问题)

以上是关于为啥 srandom(time(NULL)) 在 main() 函数和用户定义函数中的行为不同?的主要内容,如果未能解决你的问题,请参考以下文章

c语言为啥警告说从“int”转换到“float”,可能丢失数据

为啥 java.time.Clock 有区域信息?

srand(time(NULL)) 产生类似的结果[重复]

为啥 time.asctime(time.gmtime()) 忽略 GMT?

为啥 Firestore 的 'doc.get('time').toMillis' 会产生空类型错误?

time(NULL)