JavaTM 2 Platform
Standard Ed. 6

java.util
類別 Random

java.lang.Object
  繼承者 java.util.Random
所有已實作的介面:
Serializable
直接已知子類別:
SecureRandom

public class Random
extends Object
implements Serializable

此類別的實例用於產生偽隨機數(亂數)串流。此類別使用 48 位的種子,使用線性同余公式 (linear congruential form) 對其進行了修改(請參閱 Donald Knuth 的The Art of Computer Programming, Volume 3,第 3.2.1 節)。

如果用相同的種子創建兩個 Random 實例,則對每個實例進行相同的方法調用序列,它們將產生並返回相同的數字序列。為了保證此屬性的實作,為類別 Random 指定了特定的演算法。為了 Java 程式碼的完全可移植性,Java 實作必須讓類別 Random 使用此處所示的所有演算法。但是允許 Random 類別的子類別使用其他演算法,只要其符合所有方法的常規協定即可。

Random 類別實作的演算法使用一個 protected 實用工具方法,每次調用它最多可提供 32 個偽隨機(亂數) 產生的位。

很多應用程序會發現 Math.random() 方法更易於使用。

從以下版本開始:
JDK1.0
另請參見:
序列化表格

建構子摘要
Random()
          創建一個新的隨機數產生器。
Random(long seed)
          使用單個 long 種子創建一個新的隨機數產生器。
 
方法摘要
protected  int next(int bits)
          產生下一個偽隨機數(亂數)。
 boolean nextBoolean()
          返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的均勻分佈的 boolean 值。
 void nextBytes(byte[] bytes)
          產生隨機位元組並將其置於使用者提供的 byte 陣列中。
 double nextDouble()
          返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.01.0 之間均勻分佈的 double 值。
 float nextFloat()
          返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.01.0 之間均勻分佈的 float 值。
 double nextGaussian()
          返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、呈高斯(「正態」)分佈的 double 值,其平均值是 0.0,標準差是 1.0
 int nextInt()
          返回下一個偽隨機數(亂數),它是此隨機數產生器的序列中均勻分佈的 int 值。
 int nextInt(int n)
          返回一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0(包括)和指定值(不包括)之間均勻分佈的 int 值。
 long nextLong()
          返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的均勻分佈的 long 值。
 void setSeed(long seed)
          使用單個 long 種子設置此隨機數產生器的種子。
 
從類別 java.lang.Object 繼承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

建構子詳細資訊

Random

public Random()
創建一個新的隨機數產生器。此建構子將隨機數產生器的種子設置為某個值,該值與此建構子的所有其他調用所用的值完全不同。


Random

public Random(long seed)
使用單個 long 種子創建一個新的隨機數產生器。該種子是偽隨機數(亂數)產生器的內部狀態的初始值,該產生器可通過方法 next(int) 維護。

調用 new Random(seed) 等效於:

 Random rnd = new Random();
 rnd.setSeed(seed);

參數:
seed - 初始種子
另請參見:
setSeed(long)
方法詳細資訊

setSeed

public void setSeed(long seed)
使用單個 long 種子設置此隨機數產生器的種子。setSeed 的常規協定是它更改此隨機數產生器物件的狀態,使其狀態好像是剛剛使用參數 seed 作為種子創建它的狀態一樣。通過將種子自動更新為
(seed ^ 0x5DEECE66DL) & ((1L << 48) - 1)
並清除 nextGaussian() 使用的 haveNextNextGaussian 標誌,Random 類別可實作 setSeed 方法。

Random 類別實作的 setSeed 恰好只使用 48 位的給定種子。但是,通常覆寫方法可能使用 long 參數的所有 64 位作為種子值。

參數:
seed - 初始種子。

next

protected int next(int bits)
產生下一個偽隨機數(亂數)。當被所有其他方法使用時,子類別應該覆寫此方法。

next 的常規協定是,返回一個 int 值,如果參數 bits 位處於 132(包括)之間,那麼返回值的多數低位都將(大致)是單獨選擇的位值,每個位值是 01 的機會(大致)相等。通過將種子自動更新為

(seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)
並返回
(int)(seed >>> (48 - bits))Random 類別可實作 next 方法。
這是一個線性同余偽隨機數(亂數)產生器,由 D. H. Lehmer 定義,Donald E. Knuth 在 The Art of Computer Programming, Volume 3: Seminumerical Algorithms 的第 3.2.1 節中進行了描述。

參數:
bits - 隨機位。
返回:
隨機數產生器序列的下一個偽隨機(亂數) 值。
從以下版本開始:
1.1

nextBytes

public void nextBytes(byte[] bytes)
產生隨機位元組並將其置於使用者提供的 byte 陣列中。所產生的隨機位元組數等於該 byte 陣列的長度。

Random 類別按如下方式實作 nextBytes 方法:

 public void nextBytes(byte[] bytes) {
   for (int i = 0; i < bytes.length; )
     for (int rnd = nextInt(), n = Math.min(bytes.length - i, 4);
          n-- > 0; rnd >>= 8)
       bytes[i++] = (byte)rnd;
 }

參數:
bytes - 用隨機位元組填充的 byte 陣列
拋出:
NullPointerException - 如果 byte 陣列為 null
從以下版本開始:
1.1

nextInt

public int nextInt()
返回下一個偽隨機數(亂數),它是此隨機數產生器的序列中均勻分佈的 int 值。nextInt 的常規協定是,偽隨機(亂數) 地產生並返回一個 int 值。所有 232 個可能 int 值的產生概率(大致)相同。

Random 類別按如下方式實作 nextInt 方法:

 public int nextInt() {
   return next(32);
 }

返回:
下一個偽隨機數(亂數),它是此隨機數產生器的序列中均勻分佈的 int 值。

nextInt

public int nextInt(int n)
返回一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0(包括)和指定值(不包括)之間均勻分佈的 int 值。nextInt 的常規協定是,偽隨機(亂數) 地產生並返回指定範圍中的一個 int 值。所有可能的 nint 值的產生概率(大致)相同。Random 類別按如下方式實作 nextInt(int n) 方法:
 public int nextInt(int n) {
     if (n<=0)
		throw new IllegalArgumentException("n must be positive");

     if ((n & -n) == n)  // i.e., n is a power of 2
         return (int)((n * (long)next(31)) >> 31);

     int bits, val;
     do {
         bits = next(31);
         val = bits % n;
     } while(bits - val + (n-1) < 0);
     return val;
  }

前面的描述中使用了不確定的詞「大致」,因為 next 方法只是一個大致上獨自選擇位的無偏源。如果它是一個隨機選擇位的最佳源,那麼給出的演算法應該從規定範圍完全一致地選擇 int 值。

該演算法稍微有些複雜。它拒絕那些會導致不均勻分佈的值(由於 2^31 無法被 n 整除)。某個值被拒絕的概率取決於 n。最壞的情況是 n=2^30+1,拒絕的概率是 1/2,循環終止前的預計迭代次數是 2。

該演算法特別對待 n 是 2 的次方的情況:它從底層偽隨機數(亂數)產生器中返回正確的高位數。在不是特殊處理的情況中,將返回正確的 位數。眾所周知,線性同余偽隨機數(亂數)產生器(比如此類別所實作的)在其低位的值序列中週期較短。因此,如果 n 是 2 的次方(冪值較小),則這種特殊情況將大大增加此方法的後續調用所返回的值序列長度。

參數:
n - 要返回的隨機數的範圍。必須為正數。
返回:
下一個偽隨機數(亂數),在此隨機數產生器序列中 0(包括)和 n(不包括)之間均勻分佈的 int 值。
拋出:
IllegalArgumentException - 如果 n 不是正數
從以下版本開始:
1.2

nextLong

public long nextLong()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的均勻分佈的 long 值。nextLong 的常規協定是,偽隨機(亂數) 地產生並返回一個 long 值。

Random 類別按如下方式實作 nextLong 方法:

 public long nextLong() {
       return ((long)next(32) << 32) + next(32);
  }
因為 Random 類別使用只以 48 位表示的種子,所以此演算法不會返回所有可能的 long 值。

返回:
下一個偽隨機數(亂數),它是此隨機數產生器序列中均勻分佈的 long 值。

nextBoolean

public boolean nextBoolean()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的均勻分佈的 boolean 值。nextBoolean 的常規協定是,偽隨機(亂數) 地產生並返回一個 boolean 值。值 truefalse 的產生概率(大致)相同。

Random 類別按如下方式實作 nextBoolean 方法:

 public boolean nextBoolean() {
   return next(1) != 0;
 }

返回:
下一個偽隨機數(亂數),它是此隨機數產生器的序列中均勻分佈的 boolean 值。
從以下版本開始:
1.2

nextFloat

public float nextFloat()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.01.0 之間均勻分佈的 float 值。

nextFloat 的常規協定是,偽隨機(亂數) 地產生並返回一個從 0.0f(包括)到 1.0f(包括)範圍內均勻選擇(大致)的 float 值。所有可能的 224float 值(其形式為 m x 2-24,其中 m 是一個小於 224 的正整數)的產生概率(大致)相同。

Random 類別按如下方式實作 nextFloat 方法:

 public float nextFloat() {
      return next(24) / ((float)(1 << 24));
 }

前面的描述中使用了不確定的詞「大致」,因為 next 方法只是一個大致上獨立選擇位的無偏源。如果它是一個隨機選擇位的最佳來源,那麼給出的演算法應該從規定範圍完全一致地選擇 float 值。

[在 Java 的早期版本中,結果被錯誤地計算為:

 return next(30) / ((float)(1 << 30));
這可能看似等效(如果不是更好的話),但實際上由於浮點數捨入中的偏差,它會導致輕微的不均勻性:有效數的低位更可能是 0 而不是 1。]

返回:
下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.01.0 之間均勻分佈的 float

nextDouble

public double nextDouble()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.01.0 之間均勻分佈的 double 值。

nextDouble 的常規協定是,偽隨機(亂數) 地產生並返回一個從 0.0d(包括)到 1.0d(不包括)範圍內均勻選擇(大致)的 double 值。

Random 類別按如下方式實作 nextDouble 方法:

 public double nextDouble() {
       return (((long)next(26) << 27) + next(27))
           / (double)(1L << 53);
 }

前面的描述中使用了不確定的詞「大致」,因為 next 方法只是一個大致上獨立選擇位的無偏源。如果它是一個隨機選擇位的最佳源,那麼給出的演算法應該從規定範圍完全一致地選擇 double 值。

[在 Java 的早期版本中,結果被錯誤地計算為:

 return (((long)next(27) << 27) + next(27))
      / (double)(1L << 54);
這可能看似等效(如果不是更好的話),但實際上由於浮點數捨入中的偏差,它會引入較大的不均勻性:有效數的低位出現 0 的可能性是 1 的三倍!這種不均勻性在實踐中可能沒什麼關係,但我們總是力求完美。]

返回:
下一個偽隨機數(亂數),它是此隨機數產生器序列中 0.01.0 之間均勻分佈的 double
另請參見:
Math.random()

nextGaussian

public double nextGaussian()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、呈高斯(「正態」)分佈的 double 值,其平均值是 0.0,標準差是 1.0

nextGaussian 的常規協定是,偽隨機(亂數) 地產生並返回一個 double 值,該值從(大致)具有平均值 0.0 和標準差 1.0 的標準正態分佈中選擇。

Random 類別按以下這種執行緒安全的方式實作 nextGaussian 方法:

 private double nextNextGaussian;
 private boolean haveNextNextGaussian = false;

 public double nextGaussian() {
   if (haveNextNextGaussian) {
     haveNextNextGaussian = false;
     return nextNextGaussian;
   } else {
     double v1, v2, s;
     do {
       v1 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
       v2 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
       s = v1 * v1 + v2 * v2;
     } while (s >= 1 || s == 0);
     double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
     nextNextGaussian = v2 * multiplier;
     haveNextNextGaussian = true;
     return v1 * multiplier;
   }
 }
這使用了 G. E. P. Box、M. E. Muller 和 G. Marsaglia 的極坐標法 (polar method),該方法在 Donald E. Knuth 的 The Art of Computer Programming, Volume 3:Seminumerical Algorithms 的第 3.4.1 節,小節 C,演算法 P 中進行了描述。注意,它只需調用一次 StrictMath.log 和調用一次 StrictMath.sqrt> 就可以產生兩個獨立的值。

返回:
下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、呈高斯(「正態」)分佈的 double 值,其平均值是 0.0,標準差是 1.0

JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only