大家可能很多次討論過隨機數在計算機中怎樣產生的問題,在這篇文章中,我會對這個問題進行更深入的**,闡述我對這個問題的理解。
首先需要宣告的是,計算機不會產生絕對隨機的隨機數,計算機只能產生「偽隨機數」。其實絕對隨機的隨機數只是一種理想的隨機數,即使計算機怎樣發展,它也不會產生一串絕對隨機的隨機數。計算機只能生成相對的隨機數,即偽隨機數。
偽隨機數並不是假隨機數,這裡的「偽」是有規律的意思,就是計算機產生的偽隨機數既是隨機的又是有規律的。怎樣理解呢?產生的偽隨機數有時遵守一定的規律,有時不遵守任何規律;偽隨機數有一部分遵守一定的規律;另一部分不遵守任何規律。比如「世上沒有兩片形狀完全相同的樹葉」,這正是點到了事物的特性,即隨機性,但是每種樹的葉子都有近似的形狀,這正是事物的共性,即規律性。從這個角度講,你大概就會接受這樣的事實了:計算機只能產生偽隨機數而不能產生絕對隨機的隨機數。
那麼計算機中隨機數是怎樣產生的呢?有人可能會說,隨機數是由「隨機種子」產生的。沒錯,隨機種子是用來產生隨機數的乙個數,在計算機中,這樣的乙個「隨機種子」是乙個無符號整形數。那麼隨機種子是從**獲得的呢?
下面看這樣乙個c程式:
#include
static unsigned int rand_seed;
unsigned int random(void)
void random_start(void)
main()
movedata(0x0040,0x006c,fp_seg(temp),fp_off(temp),4);
這個函式用來移動記憶體資料,其中fp_seg(far pointer to segment)是取temp陣列段位址的函式,fp_off(far pointer to offset)是取temp陣列相對位址的函式,movedata函式的作用是把位於0040:006ch儲存單元中的雙字放到陣列temp的宣告的兩個儲存單元中。這樣可以通過temp陣列把0040:006ch處的乙個16位的數送給rand_seed。
random用來根據隨機種子rand_seed的值計算得出隨機數,其中這一句:
rand_seed=(rand_seed*123+59)%65536;
是用來計算隨機數的方法,隨機數的計算方法在不同的計算機中是不同的,即使在相同的計算機中安裝的不同的作業系統中也是不同的。我在linux和windows下分別試過,相同的隨機種子在這兩種作業系統中生成的隨機數是不同的,這說明它們的計算方法不同。
現在,我們明白隨機種子是從哪兒獲得的,而且知道隨機數是怎樣通過隨機種子計算出來的了。那麼,隨機種子為什麼要在記憶體的0040:006ch處取?0040:006ch處存放的是什麼?
學過《計算機組成原理與接**術》這門課的人可能會記得在編制rom bios時鐘中斷服務程式時會用到intel 8253定時/計數器,它與intel 8259中斷晶元的通訊使得中斷服務程式得以運轉,主機板每秒產生的18.2次中斷正是處理器根據定時/記數器值控制中斷晶元產生的。在我們計算機的主機板上都會有這樣乙個定時/記數器用來計算當前系統時間,每過乙個時鐘訊號週期都會使記數器加一,而這個記數器的值存放在哪兒呢?沒錯,就在記憶體的0040:006ch處,其實這一段記憶體空間是這樣定義的:
timer_low dw ? ;位址為 0040:006ch
timer_high dw ? ;位址為 0040:006eh
timer_oft db ? ;位址為 0040:0070h
時鐘中斷服務程式中,每當timer_low轉滿時,此時,記數器也會轉滿,記數器的值歸零,即timer_low處的16位二進位制歸零,而timer_high加一。rand01.c中的
movedata(0x0040,0x006c,fp_seg(temp),fp_off(temp),4);
正是把timer_low和timer_high兩個16位二進位制數放進temp陣列,再送往rand_seed,從而獲得了「隨機種子」。
注:movedata(intsegsrc,intoffsrc,intsegdest,intoffdest,unsignednumbytes)本函式將源位址(segsrc:offsrc)處的numbytes個位元組複製到目標位址(segdest:offdest)
如何產生真正隨機數
在自動化測試中,隨機測試是很常見的,一般人都知道srand和 rand 配合使用產生偽 隨機數序列,但是如何選擇seed,其實是個問題,用最簡單的time null 是可以,但是如果在乙個指令碼裡面快速執行很多遍時,很有可能時間還沒有超過 個時間顆粒度,這樣前後執行的測試取的是一樣的隨機數。一般可以...
C 如何產生隨機數
這裡要用到的是rand 函式,srand 函式,和time 函式。需要說明的是,iostream標頭檔案中就有srand函式的定義,不需要再額外引入stdlib.h 而使用time 函式需要引入ctime標頭檔案 c語言 c 怎樣產生隨機數 這裡要用到的是rand 函式,srand 函式,和time...
oracle如何產生隨機數
oracle 如何產生乙個隨機數 dbms random 1 小數 0 1 select dbms random.value from dual 2 指定範圍內的小數 0 100 select dbms random.value 0,100 from dual 3 指定範圍內的整數 0 100 se...