伪随机

Java中产生随机数的方法有两种: 
  第一种:Math.random()
  第二种:new Random()

一、java.lang.Math.Random:

  调用这个Math.Random()函数能够返回带正号的double值,取值范围是[0.0,1.0),在该范围内(近似)均匀分布。因为返回值是double类型的,小数点后面可以保留15位小数,所以产生相同的可能性非常小,在这一定程度上是随机数。

二、java.util.Random:
      Random r1 = new Random();
      Random r2 = new Random();

      Random r3 = new Random(10);
      Random r4 = new Random(10);

下面Random()的两种构造方法:

    Random():使用一个和当前系统时间对应的相对时间有关的数字作为种子数。

    Random(long seed):直接传入一个种子数。

种子的作用是什么?

  种子就是产生随机数的第一次使用值,机制是通过一个函数,将这个种子的值转化为随机数空间中的某一个点上,并且产生的随机数均匀的散布在空间中。以后产生的随机数都与前一个随机数有关。

举例
  Random r =new Random(100);
  System.out.println(r.nextInt(20));

  种子数只是随机算法的起源数字,和生成的随机数字的区间没有任何关系。

初始化时100并没有起直接作用(注意:不是没有起作用),r.nextInt(20)中的20是随机数的上限,产生的随机数为0-20的整数,不包括20。

 

举例:

复制代码
        Random r1 = new Random();
        Random r2 = new Random();
        //无参构造使用的是参数作为种子数
        Random r3 = new Random(100);
        Random r4 = new Random(100);
        //产生随机数调用nextXXX()方法
        System.out.println(r1.nextInt(10));
        System.out.println(r1.nextInt(10));
        System.out.println(r2.nextInt(10));
        System.out.println(r2.nextInt(10));
        System.out.println("-----------------");
        System.out.println(r3.nextInt(10));        
        System.out.println(r3.nextInt(10));
        System.out.println(r4.nextInt(10));
        System.out.println(r4.nextInt(10));
复制代码

结果:



复制代码
5
1
4
0
-----------------
5
0
5
0

------------------------------------------------------------------------------------------------

复制代码
5
1
4
0
-----------------
5
0
5
0

常见的随机数使用场景及生成方法 
(注意值的闭包区间) 
1、获取指定数值内的随机数 
例2:

//获取[0,n)之间的一个随机整数
public static int getRandom(int n) {
    return (int) (Math.random() * n);
}

2、获取2个数字区间内的随机数 
例3:

//获取[m,n]之间的随机数(0<=m<=n)
public static int getRandomBetweenNumbers(int m,int n){     
    return (int)(m + Math.random() * (n - m + 1));
}

此方法可用于生成随机验证码。 
3、获取指定长度的随机字符串 
  Java本身并没有生成随机字符串的方法,但我们可以通过java自带的随机数方法运算获取所需的随机字符串。 
例4:

//获取指定位数的随机字符串(包含小写字母、大写字母、数字,0<length)
public static String getRandomString(int length) {
    //随机字符串的随机字符库
    String KeyString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    StringBuffer sb = new StringBuffer();
    int len = KeyString.length();
    for (int i = 0; i < length; i++) {
       sb.append(KeyString.charAt((int) Math.round(Math.random() * (len - 1))));
    }
    return sb.toString();
}

  在这个例子中,我们先自定义一个字符串库KeyString ,然后通过Math.random()方法获取KeyString长度内的一个随机数,接着再获取该随机数对应KeyString中相应位置的一个字符,最后将随机获取并组装好的字符串返回。 
  大家可以发现,这个例子获取的随机字符串可能包含小写字母、大写字母、数字;如果说还需要包含其它字符的话,如%、#、/、* 等特殊字符,只需将相应字符添加到字符串库KeyString 中去即可;同理,若想生成只包含小写字母或者只包含数字的字符串,也只需修改字符串库KeyString 即可。可以说,这几乎是获取随机字符串的一个“万金油”方法。

4、随机生成指定概率的数字 
  获取指定值内的随机数,从理论上来说,每个数字出现概率都是一样的,但是,我们可以通过一定的运算实现按一定的概率获取数字。 
  如:我们想随机生成0、1这两个数字,但是呢,我们希望0出现的概率为70%,1出现的概率为30%;这个时候,我们可以通过用一定的随机数区间值来分别表示0、1,从而实现按概率获取随机数。 
例5:

//输出0或者1;0出现的概率为70%,1出现的概率为30%
public class TestRandom {
    public static void main(String[] args){
        Random random = new Random();
        int n = random.nextInt(100);
        if(n < 70){
            System.out.println("0");
        }else{
            System.out.println("1");
        }
    }   
}

  由以上示例可知,通过一定的运算,我们就可以按一定概率获取数字,非常简单的抽奖小游戏就可以使用这种方式来设置中奖概率。 
例6:

//简单的按概率获取数字,注意定义数组时的概率总和需为100%
public class TestRandom {
    public static void main(String[] args) {
        //各数字出现的概率分别是:1(10%)、2(20%)、3(30%)、4(40%)
        float[][] array = new float[][]{{1,10},{2,20},{3,30},{4,40}};  
        int n = luckDraw(array,new Random());
        if(1 == n){
            System.out.println("一等奖");
        }else if(2 == n){
            System.out.println("二等奖");
        }else if(3 == n){
            System.out.println("三等奖");
        }else if(4 == n){
            System.out.println("谢谢参与");
        }
    }
    //简单幸运抽奖
    public static int luckDraw(float[][] array,Random random){
        int n = 10000;  //总值
        int length = array.length;
        int random_num = random.nextInt(n); //随机数
        for(int i=0;i<length;i++){
            float before_chance = 0;    //当前概率值之前的总概率
            for(int j=0;j<i;j++){
                before_chance = before_chance + array[j][1]; 
            }
            int value = (int) (array[i][1] / 100 * n); //区间
            int up = (int) (before_chance / 100 * n);   //大于等于该值
            int under = up + value;  //小于该值
            if((up <= random_num) && (random_num < under)){
                return (int) array[i][0];
            }
        }
        return 0;
    }
}

  需要指出的是,这只是一个非常简单的小示例,只适用于要求较低的场景。真正严格意义上的抽奖有许多要求,如总出奖数量、每个奖的概率随时间的推移而变化等,有专门的一些算法去实现抽奖中的各种概率问题,感兴趣的朋友可以去了解一下。 

0
-----------------
5
0
5
0

猜你喜欢

转载自blog.csdn.net/earthchinagl/article/details/79825300