Random類 (java.util)
Random類中實現的隨機算法是僞隨機,也就是有規則的隨機。在進行隨機時,隨機算法的起源數字稱爲種子數(seed),在種子數的基礎上進行必定的變換,從而產生須要的隨機數字。
相同種子數的Random對象,相同次數生成的隨機數字是徹底相同的。也就是說,兩個種子數相同的Random對象,第一次生成的隨機數字徹底相同,第二次生成的隨機數字也徹底相同。這點在生成多個隨機數字時須要特別注意。java
一、Random對象的生成算法
Random類包含兩個構造方法,下面依次進行介紹:數組
a、public Random()
該構造方法使用一個和當前系統時間對應的相對時間有關的數字做爲種子數,而後使用這個種子數構造Random對象。
b、public Random(long seed)
該構造方法能夠經過制定一個種子數進行建立。
示例代碼:
Random r = new Random();
Random r1 = new Random(10);
再次強調:種子數只是隨機算法的起源數字,和生成的隨機數字的區間無關。
二、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的區間,也就是-2^31到2^31-1之間。
若是須要生成指定區間的int值,則須要進行必定的數學變換,具體能夠參看下面的使用示例中的代碼。
d、public int nextInt(int n)
該方法的做用是生成一個隨機的int值,該值介於[0,n)的區間,也就是0到n之間的隨機int值,包含0而不包含n。
若是想生成指定區間的int值,也須要進行必定的數學變換,具體能夠參看下面的使用示例中的代碼。
e、public void setSeed(long seed)
該方法的做用是從新設置Random對象中的種子數。設置完種子數之後的Random對象和相同種子數使用new關鍵字建立出的Random對象相同。dom
Java中存在着兩種Random函數:
1、java.lang.Math.Random;
調用這個Math.Random()函數可以返回帶正號的double值,該值大於等於0.0且小於1.0,即取值範圍是[0.0,1.0)的左閉右開區間,返回值是一個僞隨機選擇的數,在該範圍內(近似)均勻分佈。
2、java.util.Random;
在Java的API幫助文檔中,總結了一下對這個Random()函數功能的描述:
一、java.util.Random類中實現的隨機算法是僞隨機,也就是有規則的隨機,所謂有規則的就是在給定種(seed)的區間內隨機生成數字;
二、相同種子數的Random對象,相同次數生成的隨機數字是徹底相同的;
三、Random類中各方法生成的隨機數字都是均勻分佈的,也就是說區間內部的數字生成的概率均等;
下面是Java.util.Random()方法摘要
1.protected int next(int bits):生成下一個僞隨機數。
2.boolean nextBoolean():返回下一個僞隨機數,它是取自此隨機數生成器序列的均勻分佈的boolean值。
3.void nextBytes(byte[] bytes):生成隨機字節並將其置於用戶提供的 byte 數組中。
4.double nextDouble():返回下一個僞隨機數,它是取自此隨機數生成器序列的、在0.0和1.0之間均勻分佈的 double值。
5.float nextFloat():返回下一個僞隨機數,它是取自此隨機數生成器序列的、在0.0和1.0之間均勻分佈float值。
6.double nextGaussian():返回下一個僞隨機數,它是取自此隨機數生成器序列的、呈高斯(「正態」)分佈的double值,其平均值是0.0標準差是1.0。
7.int nextInt():返回下一個僞隨機數,它是此隨機數生成器的序列中均勻分佈的 int 值。
8.int nextInt(int n):返回一個僞隨機數,它是取自此隨機數生成器序列的、在(包括和指定值(不包括)之間均勻分佈的int值。
9.long nextLong():返回下一個僞隨機數,它是取自此隨機數生成器序列的均勻分佈的 long 值。
10.void setSeed(long seed):使用單個 long 種子設置此隨機數生成器的種子。
方法摘要也就這些,下面給幾個例子:
1.生成[0,1.0)區間的小數:double d1 = r.nextDouble();
2.生成[0,5.0)區間的小數:double d2 = r.nextDouble() * 5;
3.生成[1,2.5)區間的小數:double d3 = r.nextDouble() * 1.5 + 1;
4.生成-231到231-1之間的整數:int n = r.nextInt();
5.生成[0,10)區間的整數:
int n2 = r.nextInt(10);//方法一
n2 = Math.abs(r.nextInt() % 10);//方法二函數
再來簡單對比一下這兩個隨機函數到底的特色:
1.java.Math.Random()實際是在內部調用java.util.Random()的,它有一個致命的弱點,它和系統時間有關,也就是說相隔時間很短的兩個random好比:
double a = Math.random();
double b = Math.random();
即有可能會獲得兩個如出一轍的double。
2.java.util.Random()在調用的時候能夠實現和java.Math.Random()同樣的功能,並且他具備不少的調用方法,相對來講比較靈活。因此從整體來看,使用java.util.Random()會相對來講比較靈活一些。測試
應用:概率實現
按照必定的概率實現程序邏輯也是隨機處理能夠解決的一個問題。下面以一個簡單的示例演示如何使用隨機數字實現概率的邏輯。
在前面的方法介紹中,nextInt(int n)方法中生成的數字是均勻的,也就是說該區間內部的每一個數字生成的概率是相同的。那麼若是生成一個[0,100)區間的隨機整數,則每一個數字生成的概率應該是相同的,並且因爲該區間中總計有100個整數,因此每一個數字的概率都是1%。按照這個理論,能夠實現程序中的概率問題。
示例:隨機生成一個整數,該整數以55%的概率生成1,以40%的概率生成2,以5%的概率生成3。實現的代碼以下:
spa
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;
}
在程序內部,概率的邏輯就能夠按照上面的說明進行實現。
相同種子數Random對象問題前面介紹過,相同種子數的Random對象,相同次數生成的隨機數字是徹底相同的,下面是測試的代碼: 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()); }在該代碼中,對象r1和r2使用的種子數都是10,則這兩個對象相同次數生成的隨機數是徹底相同的。若是想避免出現隨機數字相同的狀況,則須要注意,不管項目中須要生成多少個隨機數字,都只使用一個Random對象便可。