Java随机数
2016-03-29 10:16
477 查看
本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示。
广义上讲,Java中的随机数的有三种产生方式:
(01).通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
(02).通过Math.random()返回一个0到1之间的double值。
(03).通过Random类来产生一个随机数,这个是专业的Random工具类,功能强大。
[b]第1种[/b]
通过System.currentTimeMillis()来获取随机数。实际上是获取当前时间毫秒数,它是long类型。使用方法如下:
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0,100)之间的int整数。方法如下:
[b]第2种[/b]
通过Math.random()来获取随机数。实际上,它返回的是0(包含)到1(不包含)之间的double值。使用方法如下:
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0,100)之间的int整数。方法如下:
Math.random();方法执行的本质是调用Random.nextDouble()方法;这里来看一个Math.random()的源码:
[b]第3种[/b]
通过Random类来获取随机数。
使用方法如下:
(01)创建Random对象。有两种方法可以创建Random对象,如下:
(02)通过Random对象获取随机数。Random支持的随机值类型包括:boolean,byte,int,long,float,double。
比如,获取[0,100)之间的int整数。方法如下:
[b]Random的函数接口[/b]
接口源码实现:
//最基本的方法,所有的随机数生成方法都调用了他,同时可以看到,Random采用的种子是AtomicLong类型的原子类,next方法来进行求解的时候使用了CAS机制保证了操作的原子类与线程安全性
[b]获取随机数示例[/b]
下面通过示例演示上面3种获取随机数的使用方法。
源码如下(RandomTest.java):
广义上讲,Java中的随机数的有三种产生方式:
(01).通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
(02).通过Math.random()返回一个0到1之间的double值。
(03).通过Random类来产生一个随机数,这个是专业的Random工具类,功能强大。
[b]第1种[/b]
通过System.currentTimeMillis()来获取随机数。实际上是获取当前时间毫秒数,它是long类型。使用方法如下:
finallongl=System.currentTimeMillis();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0,100)之间的int整数。方法如下:
finallongl=System.currentTimeMillis(); finalinti=(int)(l%100);
[b]第2种[/b]
通过Math.random()来获取随机数。实际上,它返回的是0(包含)到1(不包含)之间的double值。使用方法如下:
finaldoubled=Math.random();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0,100)之间的int整数。方法如下:
finaldoubled=Math.random(); finalinti=(int)(d*100);
Math.random();方法执行的本质是调用Random.nextDouble()方法;这里来看一个Math.random()的源码:
privatestaticRandomrandomNumberGenerator;//定义一个Random的私有的静态的变量 //对Random进行初始化操作 privatestaticsynchronizedRandominitRNG(){ Randomrnd=randomNumberGenerator; return(rnd==null)?(randomNumberGenerator=newRandom()):rnd; }
publicstaticdoublerandom(){ Randomrnd=randomNumberGenerator; if(rnd==null)rnd=initRNG(); returnrnd.nextDouble(); } 对上述源码进行简单解析:首先定义一个privatestatic的Random变量,这样所有的Math对象都可以共享这个类变量,而且只用初始化一次就可以, 执行random()方法的时候,首先判断类random变量是否已经被赋值,如果为null,则进行初始化操作,(初始化过程用Synchronized进行同步,适用于多线程环境); 如果对象不为null,说明已经完成了初始化操作,那么直接调用random的nextDouble()方法。 如果只涉及到单线程的话,这个操作等价于Randomrandom=newRandom();returnrandom.nextDouble();
[b]第3种[/b]
通过Random类来获取随机数。
使用方法如下:
(01)创建Random对象。有两种方法可以创建Random对象,如下:
Randomrandom=newRandom();//默认构造方法 Randomrandom=newRandom(1000);//指定种子数字
(02)通过Random对象获取随机数。Random支持的随机值类型包括:boolean,byte,int,long,float,double。
比如,获取[0,100)之间的int整数。方法如下:
inti2=random.nextInt(100);
[b]Random的函数接口[/b]
//构造函数(一):创建一个新的随机数生成器。 Random() //构造函数(二):使用单个long种子创建一个新随机数生成器:publicRandom(longseed){setSeed(seed);}next方法使用它来保存随机数生成器的状态。 Random(longseed) booleannextBoolean()//返回下一个“boolean类型”伪随机数。 voidnextBytes(byte[]buf)//生成随机字节并将其置于字节数组buf中。 doublenextDouble()//返回一个“[0.0,1.0)之间的double类型”的随机数。 floatnextFloat()//返回一个“[0.0,1.0)之间的float类型”的随机数。 intnextInt()//返回下一个“int类型”随机数。 intnextInt(intn)//返回一个“[0,n)之间的int类型”的随机数。 longnextLong()//返回下一个“long类型”随机数。 synchronizeddoublenextGaussian()//返回下一个“double类型”的随机数,它是呈高斯(“正常地”)分布的double值,其平均值是0.0,标准偏差是1.0。 synchronizedvoidsetSeed(longseed)//使用单个long种子设置此随机数生成器的种子。
接口源码实现:
//最基本的方法,所有的随机数生成方法都调用了他,同时可以看到,Random采用的种子是AtomicLong类型的原子类,next方法来进行求解的时候使用了CAS机制保证了操作的原子类与线程安全性
protectedintnext(intbits){ longoldseed,nextseed; AtomicLongseed=this.seed; do{ oldseed=seed.get(); nextseed=(oldseed*multiplier+addend)&mask; }while(!seed.compareAndSet(oldseed,nextseed)); return(int)(nextseed>>>(48-bits)); } //nextInt()调用了next(32)方法
publicintnextInt(){ returnnext(32); }
//nextInt(n)调用了next(31)方法,然后对n取余,这样就可以求得[0,n)之内的随机数了 publicintnextInt(intn){ if(n<=0) thrownewIllegalArgumentException("nmustbepositive"); if((n&-n)==n)//i.e.,nisapowerof2 return(int)((n*(long)next(31))>>31); intbits,val; do{ bits=next(31); val=bits%n; }while(bits-val+(n-1)<0); returnval; }
//调用了next(32),然后左移32位,在加上next(32) publiclongnextLong(){ //it'sokaythatthebottomwordremainssigned. return((long)(next(32))<<32)+next(32); }
//调用了next(1),判断结果是否是0来生成true还是false publicbooleannextBoolean(){ returnnext(1)!=0; }
//调用了next(24) publicfloatnextFloat(){ returnnext(24)/((float)(1<<24)); }
//调用了next(26)与next(27)
publicdoublenextDouble(){ return(((long)(next(26))<<27)+next(27)) /(double)(1L<<53); }
note:Random是线程安全的,用AtomicLong原子类以及CAS机制保证了操作的原子性,在进行种子设置的时候采用synchronized保证了操作的同步性, 但是多线程环境中,不建议采用Random方法,影响性能,建议采用java.util.concurrent.ThreadLocalRandom类,如果强调加密的安全性, 建议使用java.security.SecureRandom.
[b]获取随机数示例[/b]
下面通过示例演示上面3种获取随机数的使用方法。
源码如下(RandomTest.java):
1importjava.util.Random;
2importjava.lang.Math;
3
4/**
5*java的随机数测试程序。共3种获取随机数的方法:
6*(01)、通过System.currentTimeMillis()来获取一个当前时间毫秒数的long型数字。
7*(02)、通过Math.random()返回一个0到1之间的double值。
8*(03)、通过Random类来产生一个随机数,这个是专业的Random工具类,功能强大。
9*
10*@authorskywang
11*@emailkuiwu-wang@163.com
12*/
13publicclassRandomTest{
14
15publicstaticvoidmain(Stringargs[]){
16
17//通过System的currentTimeMillis()返回随机数
18testSystemTimeMillis();
19
20//通过Math的random()返回随机数
21testMathRandom();
22
23//新建“种子为1000”的Random对象,并通过该种子去测试Random的API
24testRandomAPIs(newRandom(1000),"1stRandom(1000)");
25testRandomAPIs(newRandom(1000),"2ndRandom(1000)");
26//新建“默认种子”的Random对象,并通过该种子去测试Random的API
27testRandomAPIs(newRandom(),"1stRandom()");
28testRandomAPIs(newRandom(),"2ndRandom()");
29}
30
31/**
32*返回随机数-01:测试System的currentTimeMillis()
33*/
34privatestaticvoidtestSystemTimeMillis(){
35//通过
36finallongl=System.currentTimeMillis();
37//通过l获取一个[0,100)之间的整数
38finalinti=(int)(l%100);
39
40System.out.printf("\n----System.currentTimeMillis()----\nl=%si=%s\n",l,i);
41}
42
43
44/**
45*返回随机数-02:测试Math的random()
46*/
47privatestaticvoidtestMathRandom(){
48//通过Math的random()函数返回一个double类型随机数,范围[0.0,1.0)
49finaldoubled=Math.random();
50//通过d获取一个[0,100)之间的整数
51finalinti=(int)(d*100);
52
53System.out.printf("\n----Math.random()----\nd=%si=%s\n",d,i);
54}
55
56
57/**
58*返回随机数-03:测试Random的API
59*/
60privatestaticvoidtestRandomAPIs(Randomrandom,Stringtitle){
61finalintBUFFER_LEN=5;
62
63//获取随机的boolean值
64booleanb=random.nextBoolean();
65//获取随机的数组buf[]
66byte[]buf=newbyte[BUFFER_LEN];
67random.nextBytes(buf);
68//获取随机的Double值,范围[0.0,1.0)
69doubled=random.nextDouble();
70//获取随机的float值,范围[0.0,1.0)
71floatf=random.nextFloat();
72//获取随机的int值
73inti1=random.nextInt();
74//获取随机的[0,100)之间的int值
75inti2=random.nextInt(100);
76//获取随机的高斯分布的double值
77doubleg=random.nextGaussian();
78//获取随机的long值
79longl=random.nextLong();
80
81System.out.printf("\n----%s----\nb=%s,d=%s,f=%s,i1=%s,i2=%s,g=%s,l=%s,buf=[",
82title,b,d,f,i1,i2,g,l);
83for(bytebt:buf)
84System.out.printf("%s,",bt);
85System.out.println("]");
86}
87}
相关文章推荐
- java 读取文件
- java基础知识总结5
- Java学习笔记(十六):UML类图符号以及各种关系
- Java中hashCode的作用
- java基础知识汇总4
- 通过web.xml启动spring容器遇到classnotfound解决方法
- SpringMVC国际化中的localeResolver接口!
- Java 单例真的写对了么?
- java笔记
- java14天
- javaEE项目抽取BaseService及其注意事项
- myeclipse安装svn插件并使用(本地link链接式安装插件-非侵入式安装)
- struts2头像上传练习及其注意事项
- struts2中Action的学习
- Ubuntu下设置Eclipse支持GBK和GB2312
- 深入Java集合学习之HashMap的实现原理详解
- java Properties异常:Malformed \uxxxx encoding.
- Spring AOP 详解
- java基础知识总结3
- java-poi处理excell