|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
| 上一個類別 下一個類別 | 框架 無框架 | |||||||||
| 摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 | |||||||||
java.lang.Objectjava.util.Random
public class Random
此類別的實例用於產生偽隨機數(亂數)串流。此類別使用 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() 方法更易於使用。
| 建構子摘要 | |
|---|---|
Random()
創建一個新的隨機數產生器。 |
|
Random(long seed)
使用單個 long 種子創建一個新的隨機數產生器。 |
|
| 方法摘要 | |
|---|---|
protected int |
next(int bits)
產生下一個偽隨機數(亂數)。 |
boolean |
nextBoolean()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的均勻分佈的 boolean 值。 |
void |
nextBytes(byte[] bytes)
產生隨機位元組並將其置於使用者提供的 byte 陣列中。 |
double |
nextDouble()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.0 和 1.0 之間均勻分佈的 double 值。 |
float |
nextFloat()
返回下一個偽隨機數(亂數),它是取自此隨機數產生器序列的、在 0.0 和 1.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 |
| 建構子詳細資訊 |
|---|
public Random()
public Random(long seed)
long 種子創建一個新的隨機數產生器。該種子是偽隨機數(亂數)產生器的內部狀態的初始值,該產生器可通過方法 next(int) 維護。
調用 new Random(seed) 等效於:
Random rnd = new Random();
rnd.setSeed(seed);
seed - 初始種子setSeed(long)| 方法詳細資訊 |
|---|
public void setSeed(long seed)
long 種子設置此隨機數產生器的種子。setSeed 的常規協定是它更改此隨機數產生器物件的狀態,使其狀態好像是剛剛使用參數 seed 作為種子創建它的狀態一樣。通過將種子自動更新為 (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1) 並清除 nextGaussian() 使用的 haveNextNextGaussian 標誌,Random 類別可實作 setSeed 方法。
Random 類別實作的 setSeed 恰好只使用 48 位的給定種子。但是,通常覆寫方法可能使用 long 參數的所有 64 位作為種子值。
seed - 初始種子。protected int next(int bits)
next 的常規協定是,返回一個 int 值,如果參數 bits 位處於 1 和 32(包括)之間,那麼返回值的多數低位都將(大致)是單獨選擇的位值,每個位值是 0 或 1 的機會(大致)相等。通過將種子自動更新為
(seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1) 並返回 這是一個線性同余偽隨機數(亂數)產生器,由 D. H. Lehmer 定義,Donald E. Knuth 在 The Art of Computer Programming, Volume 3: Seminumerical Algorithms 的第 3.2.1 節中進行了描述。(int)(seed >>> (48 - bits)),Random類別可實作next方法。
bits - 隨機位。
public void nextBytes(byte[] bytes)
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 陣列為 nullpublic int nextInt()
int 值。nextInt 的常規協定是,偽隨機(亂數) 地產生並返回一個 int 值。所有 232 個可能 int 值的產生概率(大致)相同。
Random 類別按如下方式實作 nextInt 方法:
public int nextInt() {
return next(32);
}
int 值。public int nextInt(int n)
int 值。nextInt 的常規協定是,偽隨機(亂數) 地產生並返回指定範圍中的一個 int 值。所有可能的 n 個 int 值的產生概率(大致)相同。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 不是正數public long nextLong()
long 值。nextLong 的常規協定是,偽隨機(亂數) 地產生並返回一個 long 值。
Random 類別按如下方式實作 nextLong 方法:
public long nextLong() {
return ((long)next(32) << 32) + next(32);
}
因為 Random 類別使用只以 48 位表示的種子,所以此演算法不會返回所有可能的 long 值。
long 值。public boolean nextBoolean()
boolean 值。nextBoolean 的常規協定是,偽隨機(亂數) 地產生並返回一個 boolean 值。值 true 和 false 的產生概率(大致)相同。
Random 類別按如下方式實作 nextBoolean 方法:
public boolean nextBoolean() {
return next(1) != 0;
}
boolean 值。public float nextFloat()
0.0 和 1.0 之間均勻分佈的 float 值。
nextFloat 的常規協定是,偽隨機(亂數) 地產生並返回一個從 0.0f(包括)到 1.0f(包括)範圍內均勻選擇(大致)的 float 值。所有可能的 224 個 float 值(其形式為 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.0 和 1.0 之間均勻分佈的 float 值public double nextDouble()
0.0 和 1.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.0 和 1.0 之間均勻分佈的 double 值Math.random()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。