在我们编写程序的过程中,有时候会用到随机数,那如何得到这个随机数呢? 在C/C++语言中,我们可以用 rand()这个函数(包含在stdlib.h头文件中),在java中,我们可以用java.lang.Math.Random()这个函数产生,当然你还可以定义一个java.util.Random对象。
其实上面那些用函数所产生的随机数都不是真正的随机数,称为“伪随机数”,真正的随机数是由物理现象所产生的,如抛硬币正反面的出现,那才是真正的随机。
那么到底随机数是如何产生的呢? 首先,得有随机种子,它是用来产生随机数的一个数,在计算机中,它是一个无符号整形数。其次,要有计算方法,也就是利用随机种子,然后采用某种计算方法即可产生随机数。
在《微机接口技术》中,我们接触一个Inter 8253 定时/计数器,它与Inter8259中断控制器的通信是的中断服务程序得以运转,主板每秒产生的18.2次中断正是处理器根据定时/记数器值控制中断芯片产生的。在主板上,这个8253可以用来计算当前的系统时间。那么当开机后,8253的这个计数器值放在哪呢? 这个值是放在内存 0040:006CH这个地址上,关于这段地址的具体描述尚未弄清,下面是摘自百科的:
TIMER_LOW DW ? ;地址为 0040:006CH
TIMER_HIGH DW ? ;地址为 0040:006EH
TIMER_OFT DB ? ;地址为 0040:0070H
时钟中断服务程序中,每当TIMER_LOW转满时,此时,记数器也会转满,记数器的值归零,即TIMER_LOW处的16位二进制归零,而TIMER_HIGH加一。rand01.c中的
正是把TIMER_LOW和TIMER_HIGH两个16位二进制数放进temp数组,再送往RAND_SEED,从而获得了“随机种子”。
所以我们就可以肯定,这个种子是来自于系统时间,即就是计算机主板上Inter 8253的计数器的值。
下面再说说计算方法,种子相同,计算方法不同,也会产生不同的随机数。不同的计算机,不同的操作系统,计算方法是不同的。
下面通过几个程序说说rand()的应用:(C语言)
最简单的应用:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6
7 printf("rand = %u\n",rand());
8 getch();
9 return 0;
10 }
这个程序在运行的时候,每次运行结果都一样,因为种子一样(这个种子是某一个固定的值)。当然不同的机子运行结果会有所不同。
如果我们要每次都产生不同的值,则可以把系统时间设置为种子,如下程序所示:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 srand((unsigned int)time(NULL));
7 printf("rand = %u\n",rand());
8 getch();
9 return 0;
10 }
这样,每次都会产生不同的值。
那么要在某一个范围内产生随机数,该怎么做呢? 看程序:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define RANGE_MIN 1
5 #define RANGE_MAX 100
6 int main()
7 {
8 int i;
9 srand((unsigned int)time(NULL));
10 for(i=0;i<20;i++)
11 {
12 printf("rand %d = %d\n",i,RANGE_MIN+(int)(RANGE_MAX*rand()/(RAND_MAX+1.0)));
13
14 }
15 getch();
16 return 0;
17 }
这样就产生了1-100之间的随机数,想换范围的话,换宏定义即可。