“真随機”與“僞随機”
- 真随機:就是我們傳統意義上了解的“随機”,随機事件如今天是否下雨,抛硬币的正反面,家門口的十字路口今天發生車禍等等。這些看似毫無規律而言的事件發生的機率是“随機的”。所謂的“真随機”,是完全雜亂的,不存在統計學參雜的,具有不可預測性和不可重制性。
- 僞随機:觀點在于“萬物皆有起因”,就像福爾摩斯所說的,如果将世界一切物質都能量化成“參數”,那麼“一切都可以預測”,就好象“今天會不會下雨”這樣的随機事件其實也是氣候狀态所決定的,是有原因的。計算機上的“僞随機”也是如此,想讓機器真的給你生成一個**機率上“随機的”**随機數是仍然沒辦法實作的。是以“僞随機”的“僞”指的是計算機産生的僞随機數既是随機的(不是“假随機”)又是有規律的。
“僞随機數”與“随機種子”
有限狀态機不能産生真正的随機數的,是以,現代計算機中,無法通過一個純算法來生成真正的随機數,無論是哪種程式設計語言,單純的算法生成的數字都是僞随機數,都是由可确定的函數通過一個種子,通過比較複雜的計算方法産生的僞随機數。而這個種子,就是我們說的**“随機種子”**。
可以這麼了解:如果将生成的“僞随機數”看作是程式的輸出的話,那麼輸入就是“随機種子”,而程式本身就是“随機函數”,如下圖所示:

每次調用随機函數,随機函數都會按順序生成随機數序列中的“僞随機數”,實際上,對于每一個特定的随機種子,随機數序列都是固定的。
Java的随機數生成器
Java提供了幾種随機數生成器,如Ramdom類、SecureRandom類等。
僞随機生成器:
随機函數可以稱作是“僞随機數發生器”,它采用特定的算法,将随機種子seed轉換成一系列的僞随機數,構成一個僞随機數序列,是以僞随機數依賴于seed的值。僞随機數的生成過程隻依賴CPU,不依賴任何外部裝置,生成速度快,不會阻塞。
Random類的使用:
public class randomNum {
long seed = 1;
Random r = new Random(seed);
public void setSeed(long s)
{
r.setSeed(s);
seed = s;
}
public void random()
{
System.out.println("generate 5 random number by seed:"+seed);
for(int i = 0; i < 5; ++i)
{
System.out.println(r.nextInt());
}
}
public static void main(String []args) {
randomNum rn=new randomNum();
rn.random();
rn.setSeed(5);
rn.random();
}
}
如果使用Random構造函數時不提供參數,系統會預設使用目前的時間作為seed。(Ramdom類裡面next方法可以讀一讀,挺有趣的)
運作結果:
generate 5 random number by seed:1
-1155869325
431529176
1761283695
1749940626
892128508
generate 5 random number by seed:5
-1157408321
758500184
379066948
-1667228448
2099829013
generate 5 random number by seed:1
-1155869325
431529176
1761283695
1749940626
892128508
代碼和結果都很好了解,用同樣的seed獲得的序列是固定的,不同的seed卻有不同的随機數數列,很好的闡述了什麼叫“僞随機”,既有機率上的随機,又有可預測的共性。
強随機數
所謂的“強随機”,就是随機函數除了依賴算法之外,引入一些随機事件源使得随機函數更加“機率上随機”。
強随機數發生器依賴于作業系統底層提供的随機事件。強随機數生成器的初始化速度和生成速度都較慢,而且由于需要一定的熵累積才能生成足夠強度的随機數,是以可能會造成阻塞。熵累積通常來源于多個随機事件源,如敲擊鍵盤的時間間隔,移動滑鼠的距離與間隔,特定中斷的時間間隔等。是以,隻有在需要生成加密性強的随機資料的時候才用它。
Java的強随機數發生器是java.security.SecureRandom類,它使用了synchronize方法保證了線程安全。
在linux的實作中,可以使用/dev/random和/dev/urandom作為随機事件源。由于/dev/random是堵塞的,在讀取随機數的時候,當熵池值為空的時候會堵塞影響性能,尤其是系統大并發的生成随機數的時候。
真随機數
http://random.org/
從1998年開始提供線上真随機數服務了,它用大氣噪音生成真随機數。他也提供了Java工具類,可以拿來使用。位址:
https://sourceforge.net/projects/randomjapi/
如在Linux系統中,SecureRandom的實作借助了/dev/random和/dev/urandom,可以使用硬體噪音生成随機數,盡量地貼近“真随機”。
C的随機數生成器
類似的,使用頭檔案<stdlib.h>中的srand和rand函數配合生成僞随機數序列。srand用于設定随機種子,rand按順序生成随機數序列中的僞随機數。
/* This program generates and prints ten random integers between 1 and RAND_MAX*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
usigned int seed;/*申明初始化器的種子,注意是usigned int型的*/
int k;
pringt("Enter a positive integer seed value: /n");
scanf("%u",&seed);
srand(seed);
printf("Random Numbers are:/n");
for(k = 1; k <= 10; k++)printf("%i",rand());
printf("/n");
return 0;
}
程式用于生成十個使用者給定種子的僞随機數。