JAVA基礎:隨機整數的生成
關鍵字:JAVA 基礎 隨機 整數 生成使用 Java 2SDK基礎類庫產生隨機數的方法很多。但是如果你跟不上這些類庫的更新腳步,你有可能正在使用的是一種低效的隨機數生成機制,更糟糕的是:你有可能得到的不是均勻分布的隨機數。本文將向你展示一種較為可靠的隨機數
關鍵字:JAVA 基礎 隨機 整數 生成使用
Java 2 SDK基礎類庫產生隨機數的方法很多。但是如果你跟不上這些類庫的更新腳步,你有可能正在使用的是一種低效的隨機數生成機制,更糟糕的是:你有可能得到的不是均勻分布的隨機數。本文將向你展示一種較為可靠的隨機數生成方法,同時與其他方法進行比較。
自從JDK最初版本發布起,我們就可以使用
java.util.Random類產生隨機數了。在JDK1.2中,Random類有了一個名為nextInt()的方法:
public int nextInt(int n)
給定一個參數n,nextInt(n)將返回一個大于等于0小于n的隨機數,即:0 <= nextInt(n) < n。
你所要做的就是先聲明一個Random的對象,在調用其nextInt(n)函數以返回隨機值。
這里有個示例,下面的代碼段將生成很多隨機數并輸出它們的平均值:
int count = 1000000;
int range = Integer.MAX_VALUE / 3 * 2;
double sum = 0;
Random rand = new Random();
for (int i=0; i<count; i++) {
sum += rand.nextInt(range);
}
System.out.println(sum/count);
執行了1000000次循環之后,得到的平均值基本上就處于隨機數范圍的中點(midpoint)。
到目前為止,事情還并不復雜,但是我們會問為什么要使用nextInt(n)?考慮一下的隨機數生成方法:
(1)使用老的方法nextInt(),沒有制定數值范圍
(2)用Math.abs()靜態函數得到(1)中產生值的絕對值
(3)對(2)的結果進行取模運算(%),得到期望范圍類的值
我們說nextInt(n)要比上述方法更好,為什么呢?參考以下的代碼段:
sum = 0;
for (int i=0; i<count; i++) {
sum += Math.abs(rand.nextInt()) % range;
}
System.out.println(sum/count);
不難發現,每次循環都多出了幾步運算。事實上,這種隨機數生成的方法存在著以下三個問題:
首先,nextInt()返回的值是趨于均勻分布在Integer.
MIN_VALUE 和 Integer.MAX_VALUE之間的。如果你取Integer.MIN_VALUE的絕對值,得到的仍然不是一個正數。事實上,Math.abs(Integer.MIN_VALUE)等于Integer.MIN_VALUE。因此,存在著這樣一種情況(雖然很少見):rand.nextInt()=Integer.MIN_VALUE,經過取絕對值Math.abs(rand.nextInt())之后,得到是一個負數。這種幾率為 1/(2^31),在我們的
測試中不太可能發生——循環次數只有1000000次。
其次,當你對nextInt()取模時,你使結果的隨機性大打折扣。隨機數中較小的值出現的幾率更大一些。這就是眾所周知的偽隨機數生成,因此我們不是用取模的方法。
原文轉自:http://www.anti-gravitydesign.com