Random⽣成随机数
Random类 (java.util)
Random类中实现的随机算法是伪随机,也就是有规则的随机。在进⾏随机时,随机算法的起源数字称为种⼦数(seed),在种⼦数的基础上进⾏⼀定的变换,从⽽产⽣需要的随机数字。
相同种⼦数的Random对象,相同次数⽣成的随机数字是完全相同的。也就是说,两个种⼦数相同的Random对象,第⼀次⽣成的随机数字完全相同,第⼆次⽣成的随机数字也完全相同。这点在⽣成多个随机数字时需要特别注意。
下⾯介绍⼀下Random类的使⽤,以及如何⽣成指定区间的随机数组以及实现程序中要求的⼏率。
1、Random对象的⽣成
Random类包含两个构造⽅法,下⾯依次进⾏介绍:
a、public Random()
该构造⽅法使⽤⼀个和当前系统时间对应的相对时间有关的数字作为种⼦数,然后使⽤这个种⼦数构造Random对象。
b、public Random(long seed)
该构造⽅法可以通过制定⼀个种⼦数进⾏创建。
⽰例代码:
复制代码代码如下:
Random r = new Random();
Random r1 = new Random(10);
再次强调:种⼦数只是随机算法的起源数字,和⽣成的随机数字的区间⽆关。
2、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的区间,也就是-231到231-1之间。
如果需要⽣成指定区间的int值,则需要进⾏⼀定的数学变换,具体可以参看下⾯的使⽤⽰例中的代码。
d、public int nextInt(int n)
该⽅法的作⽤是⽣成⼀个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0⽽不包含n。nextint()方法
如果想⽣成指定区间的int值,也需要进⾏⼀定的数学变换,具体可以参看下⾯的使⽤⽰例中的代码。
e、public void setSeed(long seed)
该⽅法的作⽤是重新设置Random对象中的种⼦数。设置完种⼦数以后的Random对象和相同种⼦数使⽤new关键字创建出的Random对象相同。
3、Random类使⽤⽰例
使⽤Random类,⼀般是⽣成指定区间的随机数字,下⾯就⼀⼀介绍如何⽣成对应区间的随机数字。以下⽣成随机数的代码均使⽤以下Random对象r进⾏⽣成:
Random r = new Random();
a、⽣成[0,1.0)区间的⼩数
复制代码代码如下:
double d1 = r.nextDouble();
直接使⽤nextDouble⽅法获得。
b、⽣成[0,5.0)区间的⼩数
复制代码代码如下:
double d2 = r.nextDouble() * 5;
因为nextDouble⽅法⽣成的数字区间是[0,1.0),将该区间扩⼤5倍即是要求的区间。
同理,⽣成[0,d)区间的随机⼩数,d为任意正的⼩数,则只需要将nextDouble⽅法的返回值乘以d即可。
c、⽣成[1,2.5)区间的⼩数
复制代码代码如下:
double d3 = r.nextDouble() * 1.5 + 1;
⽣成[1,2.5)区间的随机⼩数,则只需要⾸先⽣成[0,1.5)区间的随机数字,然后将⽣成的随机数区间加1即可。
同理,⽣成任意⾮从0开始的⼩数区间[d1,d2)范围的随机数字(其中d1不等于0),则只需要⾸先⽣成[0,d2-d1)区间的随机数字,然后将⽣成的随机数字区间加上d1即可。
d、⽣成任意整数
复制代码代码如下:
int n1 = r.nextInt();
直接使⽤nextInt⽅法即可。
e、⽣成[0,10)区间的整数
复制代码代码如下:
int n2 = r.nextInt(10);
n2 = Math.Int() % 10);
以上两⾏代码均可⽣成[0,10)区间的整数。
第⼀种实现使⽤Random类中的nextInt(int n)⽅法直接实现。
第⼆种实现中,⾸先调⽤nextInt()⽅法⽣成⼀个任意的int数字,该数字和10取余以后⽣成的数字区间为(-10,10),然后再对该区间求绝对值,则得到的区间就是[0,10)了。
同理,⽣成任意[0,n)区间的随机整数,都可以使⽤如下代码:
复制代码代码如下:
int n2 = r.nextInt(n);
n2 = Math.Int() % n);
f、⽣成[0,10]区间的整数
复制代码代码如下:
int n3 = r.nextInt(11);
n3 = Math.Int() % 11);
相对于整数区间,[0,10]区间和[0,11)区间等价,所以即⽣成[0,11)区间的整数。
g、⽣成[-3,15)区间的整数
复制代码代码如下:
int n4 = r.nextInt(18) - 3;
n4 = Math.Int() % 18) - 3;
⽣成⾮从0开始区间的随机整数,可以参看上⾯⾮从0开始的⼩数区间实现原理的说明。
h、⼏率实现
按照⼀定的⼏率实现程序逻辑也是随机处理可以解决的⼀个问题。下⾯以⼀个简单的⽰例演⽰如何使⽤随机数字实现⼏率的逻辑。
在前⾯的⽅法介绍中,nextInt(int n)⽅法中⽣成的数字是均匀的,也就是说该区间内部的每个数字⽣成的⼏率是相同的。那么如果⽣成⼀个[0,100)区间的随机整数,则每个数字⽣成的⼏率应该是相同的,⽽且由于该区间中总计有100个整数,所以每个数字的⼏率都是1%。按照这个理论,可以实现程序中的⼏率问题。
⽰例:随机⽣成⼀个整数,该整数以55%的⼏率⽣成1,以40%的⼏率⽣成2,以5%的⼏率⽣成3。实现的代码如下:
复制代码代码如下:
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;
}
在程序内部,⼏率的逻辑就可以按照上⾯的说明进⾏实现。
4、其它问题
a、相同种⼦数Random对象问题
前⾯介绍过,相同种⼦数的Random对象,相同次数⽣成的随机数字是完全相同的,下⾯是测试的代码:
复制代码代码如下:
Random r1 = new Random(10);
Random r2 = new Random(10);
for(int i = 0;i < 2;i++){
System.out.Int());
System.out.Int());
}
在该代码中,对象r1和r2使⽤的种⼦数都是10,则这两个对象相同次数⽣成的随机数是完全相同的。
如果想避免出现随机数字相同的情况,则需要注意,⽆论项⽬中需要⽣成多少个随机数字,都只使⽤⼀个Random对象即可。
b、关于Math类中的random⽅法
其实在Math类中也有⼀个random⽅法,该random⽅法的⼯作是⽣成⼀个[0,1.0)区间的随机⼩数。
通过阅读Math类的源代码可以发现,Math类中的random⽅法就是直接调⽤Random类中的nextDouble⽅法实现的。
只是random⽅法的调⽤⽐较简单,所以很多程序员都习惯使⽤Math类的random⽅法来⽣成随机数字。