摘自:http://blog.csdn.net/cashey1991/article/details/7938345

rand和srand是用于产生伪随机数的两个函数,根据参考手册rand的返回值是在[0, RAND_MAX]之间的数据,RAND_MAX在不同的系统中数值有所不同。

以下是rand和srand实现方式的一个示例(假定RAND_MAX为32767)

 1 static unsigned long next = 1;
 2 
 3 /* RAND_MAX assumed to be 32767 */
 4 int rand(void) {
 5     next = next * 1103515245 + 12345;
 6     return((unsigned)(next/65536) % 32768);
 7 }
 8 
 9 void srand(unsigned seed) {
10     next = seed;
11 }

事实上现在多数系统上的rand和srand就是使用的这种机制,只是上面取的数字或略有不同。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     int i;
 7     for (i = 0; i < 10; i++)
 8     {
 9         printf("%d ", rand());
10     }
11     getchar();
12     return 0;
13 }

在Windows下编译上面这个程序并运行,它产生的随机序列是:

41 18467 6334 26500 19169 15724 11478 29358 26962 24464

但是,当我们再运行一次时,我们会发现产生的序列是相同的。在当我们需要每次运行都产生不同的序列时,上面这样的函数显然是不行的。这是要注意的第一个陷阱。

在Linux下编译上面的程序,两次运行也会得出相同的结果,这与我们程序代码的预期是相同的。如果我们在程序的循环之前添加srand(1),我们会得到相同的序列(与不调用srand效果相同)

根据实现机制给出的代码,如果我们写的程序是如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     int i;
 7     for (i = 0; i < 10; i++)
 8     {
 9         srand(1);
10         printf("%d ", rand());
11     }
12     getchar();
13     return 0;
14 }

那它输出的序列将是相同的数,经过实际测试,确实如此:

41 41 41 41 41 41 41 41 41 41

如何写出每次运行结果都不同的随机序列呢?我们来看下例:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 
 5 int main()
 6 {
 7     int i;
 8     srand(time(NULL));
 9     for (i = 0; i < 10; i++)
10     {
11         printf("%d ", rand());
12     }
13     getchar();
14     return 0;
15 }

上面的代码,取了当前时间作为随机数种子,所以每隔一秒钟重新运行程序产生的序列都是不同的,但在同一秒钟会产生相同的序列,这不太理想。而且虽然每一秒的序列有所不同,但每个序列第一个数的数值往往相差不大,这不适用于一些要求比较严格的场合。

所以在这种情况下,最好用能取到毫秒和微秒级系统时间的函数去改写上面程序,并且在取到数时,先取一次模,再将数字拿去做种子会比较可靠一些。

如下面在Linux下的一个实现方法:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 #include <sys/time.h>
 5 
 6 int main()
 7 {
 8     int i, seed;
 9     struct timeval tv;
10     struct timezone tz = {0, 0};
11     gettimeofday(&tv, &tz);
12 
13     /* tv.tv_usec 是一个微秒级的时间 */
14     seed = tv.tv_usec % 65536;
15     srand(seed);
16     for (i = 0; i < 10; i++)
17     {
18         printf("%d ", rand());
19     }
20     getchar();
21     return 0;
22 }

这个版本的运行结果基本可以满足预期,都是不相同的序列,即使在fork多个进程运行时,也可以使每个进程所得到的序列是不相同的。

 

posted on 2013-09-30 16:27  孜求嵌道  阅读(314)  评论(0编辑  收藏  举报