Random類 (java.util)
Random類中實現的隨機演算法是偽隨機,也就是有規則的隨機。在進行隨機時,隨機演算法的起源數字稱為種子數(seed),在種子數的基礎上進行一定的變換,從而產生需要的隨機數字。
相同種子數的Random對象,相同次數產生的隨機數字是完全相同的。也就是說,兩個種子數相同的Random對象,第一次產生的隨機數字完全相同,第二次產生的隨機數字也完全相同。這點在產生多個隨機數字時需要特別注意。
下面介紹一下Random類的使用,以及如何產生指定區間的隨機數組以及實現程式中要求的幾率。
1、Random對象的產生
Random類包含兩個構造方法,下面依次進行介紹:
a、public Random()
該構造方法使用一個和當前系統時間對應的相對時間有關的數字作為種子數,然後使用這個種子數構造Random對象。
b、public Random(long seed)
該構造方法可以通過制定一個種子數進行建立。
範例程式碼:
複製代碼 代碼如下:
Random r = new Random();
Random r1 = new Random(10);
再次強調:種子數只是隨機演算法的起源數字,和產生的隨機數位區間無關。
2、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的區間,也就是-231到231-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對象相同。
3、Random類使用樣本
使用Random類,一般是產生指定區間的隨機數字,下面就一一介紹如何產生對應區間的隨機數字。以下產生隨機數的代碼均使用以下Random對象r進行產生:
Random r = new Random();
a、產生[0,1.0)區間的小數
複製代碼 代碼如下:
double d1 = r.nextDouble();
直接使用nextDouble方法獲得。
b、產生[0,5.0)區間的小數
複製代碼 代碼如下:
double d2 = r.nextDouble() * 5;
因為nextDouble方法產生的數字區間是[0,1.0),將該區間擴大5倍即是要求的區間。
同理,產生[0,d)區間的隨機小數,d為任意正的小數,則只需要將nextDouble方法的傳回值乘以d即可。
c、產生[1,2.5)區間的小數
複製代碼 代碼如下:
double d3 = r.nextDouble() * 1.5 + 1;
產生[1,2.5)區間的隨機小數,則只需要首先產生[0,1.5)區間的隨機數字,然後將產生的隨機數區間加1即可。
同理,產生任意非從0開始的小數區間[d1,d2)範圍的隨機數字(其中d1不等於0),則只需要首先產生[0,d2-d1)區間的隨機數字,然後將產生的隨機數字區間加上d1即可。
d、產生任意整數
複製代碼 代碼如下:
int n1 = r.nextInt();
直接使用nextInt方法即可。
e、產生[0,10)區間的整數
複製代碼 代碼如下:
int n2 = r.nextInt(10);
n2 = Math.abs(r.nextInt() % 10);
以上兩行代碼均可產生[0,10)區間的整數。
第一種實現使用Random類中的nextInt(int n)方法直接實現。
第二種實現中,首先調用nextInt()方法產生一個任意的int數字,該數字和10取餘以後產生的數字區間為(-10,10),然後再對該區間求絕對值,則得到的區間就是[0,10)了。
同理,產生任意[0,n)區間的隨機整數,都可以使用如下代碼:
複製代碼 代碼如下:
int n2 = r.nextInt(n);
n2 = Math.abs(r.nextInt() % n);
f、產生[0,10]區間的整數
複製代碼 代碼如下:
int n3 = r.nextInt(11);
n3 = Math.abs(r.nextInt() % 11);
相對於整數區間,[0,10]區間和[0,11)區間等價,所以即產生[0,11)區間的整數。
g、產生[-3,15)區間的整數
複製代碼 代碼如下:
int n4 = r.nextInt(18) - 3;
n4 = Math.abs(r.nextInt() % 18) - 3;
產生非從0開始區間的隨機整數,可以參看上面非從0開始的小數區間實現原理的說明。
h、幾率實現
按照一定的幾率實現程式邏輯也是隨機處理可以解決的一個問題。下面以一個簡單的樣本示範如何使用隨機數字實現幾率的邏輯。
在前面的方法介紹中,nextInt(int n)方法中產生的數字是均勻的,也就是說該區間內部的每個數字產生的幾率是相同的。那麼如果產生一個[0,100)區間的隨機整數,則每個數字產生的幾率應該是相同的,而且由於該區間中總計有100個整數,所以每個數位幾率都是1%。按照這個理論,可以實現程式中的幾率問題。
樣本:隨機產生一個整數,該整數以55%的幾率產生1,以40%的幾率產生2,以5%的幾率產生3。實現的代碼如下:
複製代碼 代碼如下:
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;
}
在程式內部,幾率的邏輯就可以按照上面的說明進行實現。
4、其它問題
a、相同種子數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對象即可。
b、關於Math類中的random方法
其實在Math類中也有一個random方法,該random方法的工作是產生一個[0,1.0)區間的隨機小數。
通過閱讀Math類的原始碼可以發現,Math類中的random方法就是直接調用Random類中的nextDouble方法實現的。
只是random方法的調用比較簡單,所以很多程式員都習慣使用Math類的random方法來產生隨機數字。