为啥 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 函数,并且很可能想知道 random
和 srandom
实际做了什么。更重要的是,因为名称在随机数上下文中很明显。你说这样的澄清是很挑剔的。
【参考方案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”,可能丢失数据
为啥 time.asctime(time.gmtime()) 忽略 GMT?