1. java.lang.Math.Random
1.1 基础
调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。
实验代码:
for(int i = 0; i < 10; ++i){
System.out.println(Math.random());
}
实验结果:
0.6672404351456087
0.003421426855892973
0.24443794443889943
0.49547249792952275
0.9262167456092021
0.06891844395293878
0.4625487756961171
0.6038531957482409
0.5725574475956846
0.13679770063093388
1.2 扩展
从0-6中生成6个不重复的随机数
实验代码:
ArrayList<Integer> randNum = new ArrayList<Integer>();
while(randNum.size() < 6){
int num = (int)(Math.random() * 6);
if(!randNum.contains(num))
randNum.add(num);
}
System.out.println("RandomNum:");
for(int i = 0; i < 6; ++i){
System.out.print(randNum.get(i) + "\t");
}
实验结果:
RandomNum:
4 0 1 5 3 2
2. java.util.Random
2.1 基础
- java.util.Random类中实现的随机算法是伪随机,也就是有规则的随机,所谓有规则的就是在给定种(seed)的区间内随机生成数字;
- 相同种子数的Random对象,相同次数生成的随机数字是完全相同的;
- Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率均等;
实验代码:
System.out.println("r1:");
Random r1 = new Random(1);
for(int i = 0; i < 5; ++i){
System.out.print(r1.nextInt(5) + "\t");
}
System.out.println("\nr2:");
Random r2 = new Random();
for(int i = 0; i < 5; ++i){
System.out.print(r2.nextInt(5) + "\t");
}
System.out.println("\nr3:");
Random r3 = new Random(1);
for(int i = 0; i < 5; ++i){
System.out.print(r3.nextInt(5) + "\t");
}
实验结果,第一次运行:
r1:
0 3 2 3 4
r2:
1 0 1 0 3
r3:
0 3 2 3 4
实验结果,第二次运行:
r1:
0 3 2 3 4
r2:
1 4 3 1 4
r3:
0 3 2 3 4
2.2 扩展
从0-6中生成6个不重复的随机数
实验代码:
ArrayList<Integer> randNumR1 = new ArrayList<Integer>();
Random r1 = new Random(1);
while(randNumR1.size() < 6){
int num = r1.nextInt(6);
if(!randNumR1.contains(num))
randNumR1.add(num);
}
System.out.println("RandomNum R1:");
for(int i = 0; i < 6; ++i){
System.out.print(randNumR1.get(i) + "\t");
}
ArrayList<Integer> randNumR2 = new ArrayList<Integer>();
Random r2 = new Random();
while(randNumR2.size() < 6){
int num = r2.nextInt(6);
if(!randNumR2.contains(num))
randNumR2.add(num);
}
System.out.println("\nRandomNum R2:");
for(int i = 0; i < 6; ++i){
System.out.print(randNumR2.get(i) + "\t");
}
ArrayList<Integer> randNumR3 = new ArrayList<Integer>();
Random r3 = new Random();
while(randNumR3.size() < 6){
int num = r3.nextInt(6);
if(!randNumR3.contains(num))
randNumR3.add(num);
}
System.out.println("\nRandomNum R3:");
for(int i = 0; i < 6; ++i){
System.out.print(randNumR3.get(i) + "\t");
}
实验结果,第一次运行:
RandomNum R1:
3 4 1 2 0 5
RandomNum R2:
1 2 4 3 0 5
RandomNum R3:
3 4 1 0 5 2
实验结果,第二次运行:
RandomNum R1:
3 4 1 2 0 5
RandomNum R2:
1 5 3 0 4 2
RandomNum R3:
4 1 5 3 2 0
3. 总结
两者都可以生成指定范围的不重复随机数,但从效率来讲,由于java.lang.Math.Random还需要浮点数乘法,以及强制类型转换,因此,显然java.util.Random效率更高。
在java.util.Random中,一旦指定了同样的种子,那么无论什么时候运行,无论生成多长的随机数,都完全一致。通常按照默认指定种子为当前时间可避免这个问题,但是两个生成器之间尽量要有一定时间间隔,否则两者时间会一致,导致依然一样。