|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
java.lang.Object java.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。