Random类 (java.util)
Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行必定的变换,从而产生须要的随机数字。
相同种子数的Random对象,相同次数生成的随机数字是彻底相同的。也就是说,两个种子数相同的Random对象,第一次生成的随机数字彻底相同,第二次生成的随机数字也彻底相同。这点在生成多个随机数字时须要特别注意。java
一、Random对象的生成算法
Random类包含两个构造方法,下面依次进行介绍:数组
a、public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字做为种子数,而后使用这个种子数构造Random对象。
b、public Random(long seed)
该构造方法能够经过制定一个种子数进行建立。
示例代码:
Random r = new Random();
Random r1 = new Random(10);
再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。
二、Random类中的经常使用方法
Random类中的方法比较简单,每一个方法的功能也很容易理解。须要说明的是,Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的概率是均等的。下面对这些方法作一下基本的介绍:
a、public boolean nextBoolean()
该方法的做用是生成一个随机的boolean值,生成true和false的值概率相等,也就是都是50%的概率。
b、public double nextDouble()
该方法的做用是生成一个随机的double值,数值介于[0,1.0)之间。
c、public int nextInt()
该方法的做用是生成一个随机的int值,该值介于int的区间,也就是-2^31到2^31-1之间。
若是须要生成指定区间的int值,则须要进行必定的数学变换,具体能够参看下面的使用示例中的代码。
d、public int nextInt(int n)
该方法的做用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n。
若是想生成指定区间的int值,也须要进行必定的数学变换,具体能够参看下面的使用示例中的代码。
e、public void setSeed(long seed)
该方法的做用是从新设置Random对象中的种子数。设置完种子数之后的Random对象和相同种子数使用new关键字建立出的Random对象相同。dom
Java中存在着两种Random函数:
1、java.lang.Math.Random;
调用这个Math.Random()函数可以返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。
2、java.util.Random;
在Java的API帮助文档中,总结了一下对这个Random()函数功能的描述:
一、java.util.Random类中实现的随机算法是伪随机,也就是有规则的随机,所谓有规则的就是在给定种(seed)的区间内随机生成数字;
二、相同种子数的Random对象,相同次数生成的随机数字是彻底相同的;
三、Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的概率均等;
下面是Java.util.Random()方法摘要
1.protected int next(int bits):生成下一个伪随机数。
2.boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值。
3.void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
4.double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布的 double值。
5.float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布float值。
6.double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的double值,其平均值是0.0标准差是1.0。
7.int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
8.int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在(包括和指定值(不包括)之间均匀分布的int值。
9.long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
10.void setSeed(long seed):使用单个 long 种子设置此随机数生成器的种子。
方法摘要也就这些,下面给几个例子:
1.生成[0,1.0)区间的小数:double d1 = r.nextDouble();
2.生成[0,5.0)区间的小数:double d2 = r.nextDouble() * 5;
3.生成[1,2.5)区间的小数:double d3 = r.nextDouble() * 1.5 + 1;
4.生成-231到231-1之间的整数:int n = r.nextInt();
5.生成[0,10)区间的整数:
int n2 = r.nextInt(10);//方法一
n2 = Math.abs(r.nextInt() % 10);//方法二函数
再来简单对比一下这两个随机函数到底的特色:
1.java.Math.Random()实际是在内部调用java.util.Random()的,它有一个致命的弱点,它和系统时间有关,也就是说相隔时间很短的两个random好比:
double a = Math.random();
double b = Math.random();
即有可能会获得两个如出一辙的double。
2.java.util.Random()在调用的时候能够实现和java.Math.Random()同样的功能,并且他具备不少的调用方法,相对来讲比较灵活。因此从整体来看,使用java.util.Random()会相对来讲比较灵活一些。测试
应用:概率实现
按照必定的概率实现程序逻辑也是随机处理能够解决的一个问题。下面以一个简单的示例演示如何使用随机数字实现概率的逻辑。
在前面的方法介绍中,nextInt(int n)方法中生成的数字是均匀的,也就是说该区间内部的每一个数字生成的概率是相同的。那么若是生成一个[0,100)区间的随机整数,则每一个数字生成的概率应该是相同的,并且因为该区间中总计有100个整数,因此每一个数字的概率都是1%。按照这个理论,能够实现程序中的概率问题。
示例:随机生成一个整数,该整数以55%的概率生成1,以40%的概率生成2,以5%的概率生成3。实现的代码以下:
spa
int n5 = r.nextInt(100); 对象
int m; //结果数字 文档
if(n5 < 55){ //55个数字的区间,55%的概率 数学
m = 1;
}else if(n5 < 95){//[55,95),40个数字的区间,40%的概率
m = 2;
}else{
m = 3;
}
由于每一个数字的概率都是1%,则任意55个数字的区间的概率就是55%,为了代码方便书写,这里使用[0,55)区间的全部整数,后续的原理同样。
固然,这里的代码能够简化,由于概率都是5%的倍数,因此只要以5%为基础来控制概率便可,下面是简化的代码实现:
int n6 = r.nextInt(20);
int m1;
if(n6 < 11){
m1 = 1;
}else if(n6 < 19){
m1= 2;
}else{
m1 = 3;
}
在程序内部,概率的逻辑就能够按照上面的说明进行实现。
相同种子数Random对象问题前面介绍过,相同种子数的Random对象,相同次数生成的随机数字是彻底相同的,下面是测试的代码: Random r1 = new Random(10); Random r2 = new Random(10); for(int i = 0;i < 2;i++){ System.out.println(r1.nextInt()); System.out.println(r2.nextInt()); }在该代码中,对象r1和r2使用的种子数都是10,则这两个对象相同次数生成的随机数是彻底相同的。若是想避免出现随机数字相同的状况,则须要注意,不管项目中须要生成多少个随机数字,都只使用一个Random对象便可。