一、随机数生成器概述
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) {
// TODO Auto-generated method stub
Random r = new Random();
double d1 = r.nextDouble(); //生成[0,1.0)区间的小数随机数
double d2 = r.nextDouble() * 5; //生成[0,5.0)之间的小数随机数
double d3 = r.nextDouble() * 1.5 + 1;//生成[1,2.5)区间的小数
int n1 = r.nextInt(); //生成任意整数
int n2 = r.nextInt(10); //生成[0,10)区间的整数
int n3 = Math.abs(r.nextInt() % 10);
int n4 = r.nextInt(11); //生成[0,10]区间的整数
int n5 = Math.abs(r.nextInt() % 11);
int n6 = r.nextInt(18) - 3; //生成[-3,15)区间的整数
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) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
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元!