1.rand(void)函数简介
- 功能:产生随机数,最大值为0X7FFFH
- 返回值:返回所产生的随机数
- 表头文件:<stdlib.h>
- 无参数
srand(seed)函数简介
- 原型:void srand(unsigned seed);
- 功能:是随机数发生器函数(rand)的初始化函数,给rand函数提供一个随机数开始的初始值(最小值)
- 参数:参数是无符号整型数据,只要满足无符号整型数据的表示范围即可
- 表头文件:<stdlib.h>
- 返回值为空
一般是先使用srand函数为rand函数提供一个初始值即rand函数从rsrand (seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。
2.rand函数单独使用
当rand函数单独使用时,系统会在rand函数前用一次srand(1),即rand函数返回的随机数从[1, RAND_MAX]。
此时randrand函数会产生规定的随机数,但是每次产生的随机数序列都是一样的。下面举例子说明这一点:
<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, re;
i = 0;
while(i < 10){
re = rand();
i++;
printf("%d ", re);
}
printf("\n");
return 0;
}
</span>
然后使用命令 gcc rand.c -o rand编译源文件,再运行生成的可执行文件
./rand 得到结果如下
1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
再次运行可执行文件得到结果如下
1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
也就是说只要运行过一次可执行文件之后,以后每次执行结果都是一样的。
3.在使用rand函数之前使用srand(seed)函数
3.1使用常数作为seed值
修改代码如下后
<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, re;
i = 0;
//使用srand函数为rand函数提供种子
srand(1189641421);
while(i < 3){
re = rand();
i++;
printf("%d ", re);
}
printf("\n");
return 0;
}
</span>
通过编译和执行步骤后得到一下结果:
645298965 371103934 491315407
再次运行可执行文件得到结果如下
645298965 371103934 4 91315407
也就是说使用固定值seed初始化rand函数后每次得到的随机序列也是一样的。只是范围发生变化而已,范围变为[seed, RAND_MAX]
3.2使用不断变化的seed作为srand参数
将以上代码改为以下形式:
<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main(void)
{
int i, re;
i = 0;
//使用srand函数为rand函数提供种子
srand((unsigned)time(NULL));
while(i < 3){
re = rand();
i++;
printf("%d ", re);
}
printf("\n");
return 0;
}
</span>
经编译后初次运行后的结果为:
861061899 480645075 280256411
再次运行的结果为
1793735524 811069568 731560706
再次运行得到的结果为
475626611 1524657326 1104320056
这就是说只要种子发生生了变化则随机数返回的随机序列就会不同。srand((unsigned)time(NULL))表明每次运行程序时都是一个变量。关于time系列的函数留到以后的篇章中笔记。
4.随机得到[L,U]之间的整数
- rand() / double(RAND_MAX)可以取得0~1之间的浮点数
- rand() / (double)(RAND_MAX/10)取更大范围的随机浮点数1~10,至于100,1000的情况,如此类推
- rand() % (U+1 - L) + L 随机得到得到[L,U]之间的整数。
5.总结
随机数函数的主要用途是用在switch或者if..else中。随机的决定一些选项,若rand(seed)在系统每次启动时都会发生变化,则相同算法产生的结果就会不同。
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main(void)
{
int i, re;
i = 0;
//使用srand函数为rand函数提供种子
srand((unsigned)time(NULL));
while(i < 3){
re = rand();
i++;
printf("%d ", re);
}
printf("\n");
return 0;
}
6 Floyd 算法
Floyd算法用以产生不重复的随机整数。先笔记产生(1, n)的m个不重复的随机整数的方法。
6.1 基本算法
s = empty size = 0 while size < m do T = randint(1, n) if T not in S then insert T in s size++ |
randint(1, n)是调用rand函数以产生1 ~ n的一个整数。
此算法潜在的问题:
- m > n时,会永远执行此段代码。
- m <= n时且m值又较大时,由于randint函数的随机性也可能导致此算法久久的执行()。
6.2 Floyd算法
(1) 递归实现
function sample (m, n) if m = 0 then return else s = sample(m-1, n-1) T = randint(1, n) if T is not in s then insert T in s else insert n is s return s |
从1 ~ n - m中产生一个随机整数,若此整数已经存在于s中则将n-m存储于s中,这样就避免了上一个算法潜在的第二个问题。
(2) Floyd的非递归实现
递归是代码耗时的一个典型,在实际应用中,若程序的大多数运行时间都在Floyd算法之上的话可以将Floyd递归算法优化为非递归的形式以提高程序的效率。
s = empty for j = n-m +1 to n do T = randint(1, j) if T is not in s then insert T in s else insert T in s |
2014-02-16
Note Over。