一、随机数生成器概述
Java中的Random类主要用来生成随机数,Random类中实现的随机算法是伪随机(也称为有规则的随机)。在进行随机生成时,随机生成算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生不同的随机数字。
种子数决定了生成数,相同种子数的Random对象,相同次数生成的随机数字是完全相同的。因此,在生成多个随机数时,需要特别注意特们的seed是否相同。
Java的Random类和Scanner类一样都封装在在java.util中,单独使用的情况非常少,通常搭配一些其他的方法来生成我们需要的随机数。
1、导入Random类
import java
.util
.Random
;
2、Random对象的生成
Random类包含两个构造方法,一个是无参数的构造方法public Random(),另一个是有参数的构造方法public Random(seed):
(1)public Random()
通过实例化一个Random类对象可以创建一个随机数生成器,无参数的Random对象构造方法是使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象,seed是不需要指定的。
Random r
= new Random();
r:Random对象
Random类提供了生成各种数据类型随机数的方法,j
(2)public Random(seed)
有参数的Random对象构造方法是使用一个指定数字作为种子数,然后使用这个种子数构造Random对象。
Random r
= new Random(seed
);
r:Random对象Seed:随机数种子,即随机算法的起源数
二、Random类中的常用方法
Random提供了生成各种数据类型的随机数构造方法:
方法返回值功能
nextBoolean()boolean生成一个随机的boolean值,生成true和false的值几率相等,也就是都是50%的几率。nextDouble()double生成一个随机的double值,数值介于[0,1.0)之间。nextInt()int生成一个随机的int值,该值介于int的区间,也就是
−
2
31
-2^{31}
−231到
2
31
−
1
2^{31} -1
231−1之间。nextInt(int n)int生成一个随机的int值,该值介于[0,n)的区间。如果想生成指定区间的int值,也需要进行一定的数学变换。nextLong()long生成一个随机的long值nextFloat()float生成一个随机的float值nextGaussian()double生成一个概率密度为高斯分布的double值setSeed(long seed)/重新设置Random对象中的种子数,返回对应种子的随机数。
三、Random类中方法的应用
1、生成指定区间的随机数字的方法
编号目的使用的方法说明
1生成[0,1.0)区间的小数随机数nextDouble()直接使用nextDouble方法获得2生成[0,5.0)之间的小数随机数nextDouble()生成[0,d)区间的随机小数,d为任意正的小数/整数,则只需要将nextDouble方法的返回值乘以d即可3生成[1,2.5)之间的小数随机数nextDouble()首先生成[0,1.5)区间的随机数字,然后将生成的随机数区间加1即可4生成任意随机整数nextInt()直接使用nextInt方法5生成[0,10)区间的整数nextInt(int n)使用nextInt(int n)方法直接实现。或者先调用nextInt()方法随机生成一个int数字,该数字和10取余以后生成的数字区间为(-10,10),然后再对该区间求绝对值,则得到的区间就是[0,10)了。6生成[0,10]区间的整数nextInt(int n)[0,10]和[0,11)区间等价,所以生成[0,11)区间的整数即可。7生成[-3,15)区间的整数nextInt(int n)与非从0开始的小数区间实现原理相同
2、生成指定区间以及数方法的实现
import java
.util
.Random
;
public class Randomdemo {
public static void main(String
[] args
) {
Random r
= new Random();
double d1
= r
.nextDouble();
double d2
= r
.nextDouble() * 5;
double d3
= r
.nextDouble() * 1.5 + 1;
int n1
= r
.nextInt();
int n2
= r
.nextInt(10);
int n3
= Math
.abs(r
.nextInt() % 10);
int n4
= r
.nextInt(11);
int n5
= Math
.abs(r
.nextInt() % 11);
int n6
= r
.nextInt(18) - 3;
int n7
= Math
.abs(r
.nextInt() % 18) - 3;
System
.out
.println("生成[0,1.0)区间的小数随机数"+ d1
);
System
.out
.println("生成[0,5.0)之间的小数随机数"+ d2
);
System
.out
.println("生成[1,2.5)区间的小数"+ d3
);
System
.out
.println("生成任意整数"+ n1
);
System
.out
.println("生成[0,10)区间的整数方法1"+ n2
);
System
.out
.println("生成[0,10)区间的整数方法2"+ n3
);
System
.out
.println("生成[0,10]区间的整数方法1"+ n4
);
System
.out
.println("生成[0,10]区间的整数方法2"+ n5
);
System
.out
.println("生成[0,10]区间的整数"+ n6
);
System
.out
.println("生成[-3,15)区间的整数"+ n7
);
}
}
Console
:
生成
[0,1.0)区间的小数随机数
0.8620178561623245
生成
[0,5.0)之间的小数随机数
2.7088745792313547
生成
[1,2.5)区间的小数
1.1084673674461711
生成任意整数
-1950627867
生成
[0,10)区间的整数方法
18
生成
[0,10)区间的整数方法
23
生成
[0,10]区间的整数方法
13
生成
[0,10]区间的整数方法
27
生成
[0,10]区间的整数
5
生成
[-3,15)区间的整数
7
三、相同种子数的Random对象问题
相同种子数的Random对象,相同次数生成的随机数字是完全相同的。
import java
.util
.Random
;
public class Randomdemo {
public static void main(String
[] args
) {
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());
}
}
}
Console
:
-1157793070
-1157793070
1913984760
1913984760
在该代码中,对象r1和r2使用的种子数都是10,则这两个对象相同次数生成的随机数是完全相同的。如果想避免出现随机数字相同的情况,则需要注意,无论项目中需要生成多少个随机数字,都只使用一个Random对象即可。
四、Math的random方法和Random类的
Math类中也有一个random方法,该random方法的工作是生成一个[0,1.0)区间的随机小数。但实际上,Math类中的random方法就是直接调用Random类中的nextDouble方法实现的。只是random方法的调用比较简单,所以很多人都习惯使用Math类的random方法来生成随机数字。
实例1:模拟微信抢红包功能
import java
.util
.Scanner
;
import java
.util
.Random
;
public class RedBags {
public static void main(String
[] args
) {
System
.out
.println("--------------模拟微信抢红包---------");
Scanner sc
= new Scanner(System
.in
);
System
.out
.println("输入红包总额");
Double total
= sc
.nextDouble();
System
.out
.println("输入红包个数");
int bagsum
= sc
.nextInt();
double min
= 0.01;
Random rd
= new Random();
if(total
/bagsum
== 0.01) {
for(int i
= 1;i
<bagsum
;i
++) {
double money
= min
;
total
-= money
;
System
.out
.println("第"+i
+"个红包"+String
.format("%.2f", money
)+"元!");
}
}
else if(total
/bagsum
<0.01) {
System
.out
.println("要保证每个人都能拿到1分钱哦");
return;
}
else {
for(int i
= 1;i
<bagsum
;i
++) {
double max
= total
- (bagsum
- i
)*min
;
double bound
= max
- min
;
double safe
= (double)rd
.nextInt((int)(bound
*100))/100;
double money
= safe
+min
;
total
= total
- money
;
System
.out
.println("第"+i
+"个红包"+String
.format("%.2f",money
)+"元!");
}
}
System
.out
.println("第"+bagsum
+"个红包"+String
.format("%.2f", total
)+"元!");
sc
.close();
}
}
Console
:
--------------模拟微信抢红包
---------
输入红包总额
1
输入红包个数
200
要保证每个人都能拿到
1分钱哦
Console
:
--------------模拟微信抢红包
---------
输入红包总额
100
输入红包个数
15
第
1个红包
32.07元!
第
2个红包
4.63元!
第
3个红包
13.40元!
第
4个红包
17.00元!
第
5个红包
24.16元!
第
6个红包
1.88元!
第
7个红包
1.16元!
第
8个红包
1.77元!
第
9个红包
2.52元!
第
10个红包
0.24元!
第
11个红包
0.49元!
第
12个红包
0.12元!
第
13个红包
0.52元!
第
14个红包
0.02元!
第
15个红包
0.02元!
五、小结