站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题J2SE的随机联函数!!

J2SE的随机联函数!!

摘要: 这里涉及到伪随机数的概念,什么是伪随机数呢

java.util.Random() = new Random();
int num = nextInt(8);

错在哪里啊?


 生成真正的随机数!

这里涉及到伪随机数的概念,什么是伪随机数呢?伪随机数是使用一些称为种子(seed)的初始值通过某种算法得到的。这个算法是确定的,因此产生的数字序列在统计上并不是随机的。不过,假如这个算法优良,那么结果得到的数字序列就能够通过许多合理的随机性测试。这些数字通常被称为伪随机数(psreudorandom number)。除非你知道算法和种子,否则就不大能推测出这个序列[1]。 

好了,下面来看一下这句话是什么意思:
srand(time(NULL));    
先看srand()函数有什么作用。它是用来设定种子(seed)的,例:srand(n),则n就是你设定的种子。如果每次设定的种子相同,比如srand(1),那么相当于不调用srand()函数(注意 :如果不显式调用srand()函数,系统只会默认调用一次srand(1)函数,即在第一个rand()函数之前调用;执行第2个第3个……rand()之前不会再调用srand(1)),那么接下来你再调用rand(),得到的随机数序列是相同的,这里给一个例子:

windows 32 console

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

void main( void )
{
   int i;

   /* Seed the random-number generator with current time so that
    * the numbers will be different every time we run.
    */
   //srand( (unsigned)time( NULL ) );

   /* Display 10 numbers. */
   for( i = 0;   i < 10;i++ )
      printf( "  %6d\n", rand() );
}

注意,这个程序中,我把srand( (unsigned)time( NULL ) )给注释起来了,所以每次运行该程序时,种子是默认给出的,都是同一个值,(vc++中默认种子的值为1),既然种子一样,就像我前面提到的,算法是一定的,所以每次产生的随机数序列都是相同的。在我的电脑上每次运行程序都产生这10个数:

41

18467

6334

26500

19169

15724

11478

29358

26962

24464

所以说这些数是伪随机数。因为真正的随机数每次产生时都不应该相同,包括这个序列也不应该相同。所以说我们要产生真正的随机数,就应当在每次调用rand()之前设定不同的种子,怎样做到这一点呢?使用time(NULL)。

time(NULL)返回的是一个time_t类型的数据,实际上是一个无符号整型(unsigned int)的数据,在这个32位的无符号数中,高16位存放当前Date(年月日)的信息,低16位存当前放Time(时分秒)的信息。时间是在不断变化的,所以每次调用time(NULL)返回的值是不同的(当然两次调用的时间间隔大于等于1秒才行,因为time_t中的信息只精确到秒)
这样srand(time(NULL));    就可以保证每次都会设定新的 种子,从而再调用rand()时会得到不同的随机数序列:再给个例子[2]这个例子仅仅是把前面的例子多加了一句srand(time(NULL));    )

windows 32 console

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

void main( void )
{
   int i;

   /* Seed the random-number generator with current time so that
    * the numbers will be different every time we run.
    */
   srand(time(NULL));   

   /* Display 10 numbers. */
   for( i = 0;   i < 10;i++ )
      printf( "  %6d\n", rand() );
}

这样每次运行程序都会得到10个不同的数,并且每次得到的这10个数都是不同的(注意理解我的意思,每次产生的10个数组成的序列不同)。

注意time(NULL)的作用其实就是将当前时间保存到一个UNIT中返回,

time_t osBinaryTime=time(NULL);相当于以下代码:

CTime   t=CTime::GetCurrentTime();

time_t   osBinaryTime=t.GetTime(); >
应该是产生0到99 的整数,如果要0-100左闭右开区间内整数的话,只要a=rand.nextInt(100) 就可以了。nextInt是从0开始的,然后参数100,是生成的整数都小于100的,然后后面再适当加个小数,小数的生成办法rand.nextDouble(),因此只要a=rand.nextInt(100) + rand.nextDouble(),就可以了。另外由于是左闭,因此应该rand.nextInt(100) 值为0的时候,再用一个随机数来控制是否要加后面的小数就OK了。下面给出参考代码和不精确的测试。
<table border="0" cellspacing="1" cellpadding="3" bgcolor="#999999"><tr><td width="1" align="left" bgcolor="#dddddd" valign="top">

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</td><td align="left" bgcolor="#ffffff" valign="top">
/**
     * @param args
     */
    public static void main(String[] args) {
        Random rand = new Random();
        double a = 0;
        int b = 0;
        double c = 0;
        int d = 0;
        boolean zeroFlag = true;
        boolean bottomFlag = true;
        boolean topFlag = true;
        for (int i = 0; i < 100000000; i++) {
            b = rand.nextInt(100);
            c = rand.nextDouble();
            d = rand.nextInt(100);
            //当b为0时,d也为0的概率为1/100,设置此时当b==0时a为0的概率为1/100
            if (b == 0 && d == 0) {
                a = 0;
            } else {
                a = b + c;
            }
            // 如果产生的随机数大于等于100或者小于0,结束循环,提示出错
            if (a >= 100 && a < 0) {
                System.out.println("False!");
                System.out.println(b);
                System.out.println(c);
                break;
            }
            // 产生的随机数在0-1之间,提示下线正确
            if (a < 1 && a > 0 && bottomFlag) {
                System.out.println("bottomLine is OK!");
                bottomFlag = false;
            }
            // 产生的随机数值为0,提示左闭值0正确
            if (a == 0 && zeroFlag) {
                System.out.println("zero is OK!");
                zeroFlag = false;
            }
            //产生的随机数超过99,提示上线正确
            if (a > 99 && topFlag) {
                System.out.println("topLine is OK!");
                topFlag = false;
            }
        }
        System.out.println("End!");
    }


 

↑返回目录
前一篇: 如何才算掌握Java(J2SE篇)
后一篇: 使用J2SE API读取Properties文件的六种方法