为什么产生随机数时,种子位置改变会产生这样截然不同的结果?

时间:2022-12-03 19:04:19
今天下午14:00多,我发了这样一个贴子“怎样随机产生一系列0-10的整数呢?我要的是随机,而非伪随机!多谢!”http://www.csdn.net/Expert/topic/498/498797.shtm),有许多朋友慷慨相助,我也取得了较满意结果。仍有一问,向朋友们请教:
  为什么把srand((unsigned)time( NULL ));提到主函数就会产生出满意的结果?而把srand((unsigned)time( NULL ));放到子函数int random(int a)中却会产生每运行一次就会产生相同的序列?
程序代码如下:

#include<stdlib.h>
#include<stdio.h>
#include<time.h>
int random(int a);
int main()
{
int d;
int j;
srand((unsigned)time( NULL ));


for(j=1;j<20;j++)
{
d=random(10);
printf("d=:%d\n",d);

}
return 0;
}
int random(int a)
{
int c;
c=rand();
while(c>a)
c=rand();
return c;
}


11 个解决方案

#1


呵呵,我也有相同的疑问,如果放在for循环里也不能得到正确的结果,不知道为什么……

#2


随机函数好象是每次产生的数字都是一样的,因为这个函数产生数值的时候是通过一个算法实现的,而不是通过系统时钟产生的,所以在用的时候你还要判断一下的比较好

#3


我上面的代码是正确的。每运行一次都可以得到不同的一系列0-10的整数。

朋友们请帮帮忙吧
参与皆有分相送!





































































#4


我知道计算机中的rand()是个伪随机函数。但给了种子以后,就会变得更像随机数一些。

#5


rand()是个伪随机函数, 你认为计算机可以产生 真的随机数吗?我看有问题,好点的随机数发生器,只是周期很长而已。如果你需要比较好的随机数发生器,可以试试 CryptoAPI 的。也可以随便下载一个 加密库如 cryptlib,用里面的随机数发生器还不错。

#6



放在子函数里和for循环里不能产生看似随机的数会不会和编译器的优化有关呢?

#7


m m m…………………………

#8


你用srand()设置种子数的时候,是按照当前时刻(time)确定一个种子数,由于按照时间来取,种子数本身就可以具有随机性,其产生的伪随机数才同样具有真正的随机数.
使用种子数产生了一次伪随机数后,也就自动回确定一个种子数,为下一次的伪随机产生基础.
所以:
如果你放到主循环外,第一次的种子数是按照运行程序的时刻来确定的,运行该程序的时刻是随机的,所以能产生真正的随机数.
如果你放到for循环内调用的子函数内,由于计算机处理速度非常快,for循环中j=0,j =1,j =5,j =...的时候,time()函数的返回结果是完全相同的,从而导致你每次循环都回产生一个种子数,而这个种子数又是相同的.从而整个结果反而不随机了.

#9


请问crytoapid在哪里能够下载
谢谢birdinfly!既然速度非常快,那么在主程序中的种子函数返回结果也应该相同了? 

#10


不是的,主程序中,你什么时候运行程序的时间是随机的,导致第一次的种子数是随机的.
这个种子数随机了后,如果你没有再次调用srand()设置新的随机种子数,就采用一个伪随机的种子数作为下次的随机种子.

而你在for循环中,每次重取随机数的时候,其实你都重新取了一次随机数SRAND(time()),而time()得到的时间产生的种子数是一样的了,所以每次产生新的随机数的种子数都是相同的了. 

#11


其实srand()和rand()不是真的产生随机数,它只不过产生不串随机数列,而这串随机数列是什么,是由srand()通过设置种子数来实现。只要种子数一样,则它的随机数列就一样。而当你把srand()放在循环里时,它每次都初始化随机数列为同一个种子数(对于电脑来说,在一个循环中它的时间是一样的),并且是从随机数列的开头开始产生随机数。
如果你将这个语句:srand((unsigned)time( NULL ));
改为srand(1); // 只需参数为任意常量。
则多次运行程序的结果将都是一样的。

#1


呵呵,我也有相同的疑问,如果放在for循环里也不能得到正确的结果,不知道为什么……

#2


随机函数好象是每次产生的数字都是一样的,因为这个函数产生数值的时候是通过一个算法实现的,而不是通过系统时钟产生的,所以在用的时候你还要判断一下的比较好

#3


我上面的代码是正确的。每运行一次都可以得到不同的一系列0-10的整数。

朋友们请帮帮忙吧
参与皆有分相送!





































































#4


我知道计算机中的rand()是个伪随机函数。但给了种子以后,就会变得更像随机数一些。

#5


rand()是个伪随机函数, 你认为计算机可以产生 真的随机数吗?我看有问题,好点的随机数发生器,只是周期很长而已。如果你需要比较好的随机数发生器,可以试试 CryptoAPI 的。也可以随便下载一个 加密库如 cryptlib,用里面的随机数发生器还不错。

#6



放在子函数里和for循环里不能产生看似随机的数会不会和编译器的优化有关呢?

#7


m m m…………………………

#8


你用srand()设置种子数的时候,是按照当前时刻(time)确定一个种子数,由于按照时间来取,种子数本身就可以具有随机性,其产生的伪随机数才同样具有真正的随机数.
使用种子数产生了一次伪随机数后,也就自动回确定一个种子数,为下一次的伪随机产生基础.
所以:
如果你放到主循环外,第一次的种子数是按照运行程序的时刻来确定的,运行该程序的时刻是随机的,所以能产生真正的随机数.
如果你放到for循环内调用的子函数内,由于计算机处理速度非常快,for循环中j=0,j =1,j =5,j =...的时候,time()函数的返回结果是完全相同的,从而导致你每次循环都回产生一个种子数,而这个种子数又是相同的.从而整个结果反而不随机了.

#9


请问crytoapid在哪里能够下载
谢谢birdinfly!既然速度非常快,那么在主程序中的种子函数返回结果也应该相同了? 

#10


不是的,主程序中,你什么时候运行程序的时间是随机的,导致第一次的种子数是随机的.
这个种子数随机了后,如果你没有再次调用srand()设置新的随机种子数,就采用一个伪随机的种子数作为下次的随机种子.

而你在for循环中,每次重取随机数的时候,其实你都重新取了一次随机数SRAND(time()),而time()得到的时间产生的种子数是一样的了,所以每次产生新的随机数的种子数都是相同的了. 

#11


其实srand()和rand()不是真的产生随机数,它只不过产生不串随机数列,而这串随机数列是什么,是由srand()通过设置种子数来实现。只要种子数一样,则它的随机数列就一样。而当你把srand()放在循环里时,它每次都初始化随机数列为同一个种子数(对于电脑来说,在一个循环中它的时间是一样的),并且是从随机数列的开头开始产生随机数。
如果你将这个语句:srand((unsigned)time( NULL ));
改为srand(1); // 只需参数为任意常量。
则多次运行程序的结果将都是一样的。