導航:首頁 > 知識科普 > 偽隨機數生成方法有哪些

偽隨機數生成方法有哪些

發布時間:2023-07-11 14:30:28

❶ 介紹java 產生隨機數的兩種方式

一個是使用Math.random();只能產生double的隨機值
另一個是工作Random類的相關方法,有多種類型的隨機值的獲取方法
如nextBoolean()、
nextInt()等,具體可以參考API

什麼是偽隨機數與真隨機數

首先需要聲明的是,計算機不會產生絕對隨機的隨機數,計算機只能產生「偽隨機數」。其實絕對隨機的隨機數只是一種理想的隨機數,即使計算機怎樣發展,它也不會產生一串絕對隨機的隨機數。計算機只能生成相對的隨機數,即偽隨機數。

偽隨機數並不是假隨機數,這里的「偽」是有規律的意思,就是計算機產生的偽隨機數既是隨機的又是有規律的。怎樣理解呢?產生的偽隨機數有時遵守一定的規律,有時不遵守任何規律;偽隨機數有一部分遵守一定的規律;另一部分不遵守任何規律。比如「世上沒有兩片形狀完全相同的樹葉」,這正是點到了事物的特性,即隨機性,但是每種樹的葉子都有近似的形狀,這正是事物的共性,即規律性。從這個角度講,你大概就會接受這樣的事實了:計算機只能產生偽隨機數而不能產生絕對隨機的隨機數。

那麼計算機中隨機數是怎樣產生的呢?有人可能會說,隨機數是由「隨機種子」產生的。沒錯,隨機種子是用來產生隨機數的一個數,在計算機中,這樣的一個「隨機種子」是一個無符號整形數。那麼隨機種子是從哪裡獲得的呢?

下面看這樣一個C程序:

//rand01.c
#include<dos.h>

static unsigned int RAND_SEED;

unsigned int random(void)
{
RAND_SEED=(RAND_SEED*123+59)%65536;
return(RAND_SEED);
}

void random_start(void)
{
int temp[2];
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
RAND_SEED=temp[0];
}

main()
{
unsigned int i,n;
random_start();
for(i=0;i<10;i++)
printf("%u\t",random());
printf("\n");
}

這個程序(rand01.c)完整地闡述了隨機數產生的過程:
首先,主程序調用random_start()方法,random_start()方法中的這一句我很感興趣:

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,從而獲得了「隨機種子」。

現在,可以確定的一點是,隨機種子來自系統時鍾,確切地說,是來自計算機主板上的定時/計數器在內存中的記數值。這樣,我們總結一下前面的分析,並討論一下這些結論在程序中的應用:

1.隨機數是由隨機種子根據一定的計算方法計算出來的數值。所以,只要計算方法一定,隨機種子一定,那麼產生的隨機數就不會變。

看下面這個C++程序:

//rand02.cpp
#include <iostream>
#include <ctime>
using namespace std;

int main()
{
unsigned int seed=5;
srand(seed);
unsigned int r=rand();
cout<<r<<endl;
}

在相同的平台環境下,編譯生成exe後,每次運行它,顯示的隨機數都是一樣的。這是因為在相同的編譯平台環境下,由隨機種子生成隨機數的計算方法都是一樣的,再加上隨機種子一樣,所以產生的隨機數就是一樣的。

2.只要用戶或第三方不設置隨機種子,那麼在默認情況下隨機種子來自系統時鍾(即定時/計數器的值)

看下面這個C++程序:

//rand03.cpp
#include <iostream>
#include <ctime>
using namespace std;

int main()
{
srand((unsigned)time(NULL));
unsigned int r=rand();
cout<<r<<endl;
return 0;
}

這里用戶和其他程序沒有設定隨機種子,則使用系統定時/計數器的值做為隨機種子,所以,在相同的平台環境下,編譯生成exe後,每次運行它,顯示的隨機數會是偽隨機數,即每次運行顯示的結果會有不同。

3.建議:如果想在一個程序中生成隨機數序列,需要至多在生成隨機數之前設置一次隨機種子。

看下面這個用來生成一個隨機字元串的C++程序:

//rand04.cpp
#include<iostream>
#include<time.h>
using namespace std;
int main()
{
int rNum,m=20;
char *ch=new char[m];

for ( int i = 0; i<m; i++ ){
//大家看到了,隨機種子會隨著for循環在程序中設置多次
srand((unsigned)time(NULL));
rNum=1+(int)((rand()/(double)RAND_MAX)*36); //求隨機值
switch (rNum){
case 1: ch[i]='a';
break ;
case 2: ch[i]='b';
break ;
case 3: ch[i]='c';
break ;
case 4: ch[i]='d';
break ;
case 5: ch[i]='e';
break ;
case 6: ch[i]='f';
break ;
case 7: ch[i]='g';
break ;
case 8: ch[i]='h';
break ;
case 9: ch[i]='i';
break ;
case 10: ch[i]='j';
break ;
case 11: ch[i]='k';
break ;
case 12: ch[i]='l';
break ;
case 13: ch[i]='m';
break ;
case 14: ch[i]='n';
break ;
case 15: ch[i]='o';
break ;
case 16: ch[i]='p';
break ;
case 17: ch[i]='q';
break ;
case 18: ch[i]='r';
break ;
case 19: ch[i]='s';
break ;
case 20: ch[i]='t';
break ;
case 21: ch[i]='u';
break ;
case 22: ch[i]='v';
break ;
case 23: ch[i]='w';
break ;
case 24: ch[i]='x';
break ;
case 25: ch[i]='y';
break ;
case 26: ch[i]='z';
break ;
case 27:ch[i]='0';
break;
case 28:ch[i]='1';
break;
case 29:ch[i]='2';
break;
case 30:ch[i]='3';
break;
case 31:ch[i]='4';
break;
case 32:ch[i]='5';
break;
case 33:ch[i]='6';
break;
case 34:ch[i]='7';
break;
case 35:ch[i]='8';
break;
case 36:ch[i]='9';
break;
}//end of switch
cout<<ch[i];
}//end of for loop

cout<<endl;
return 0;
}

而運行結果顯示的隨機字元串的每一個字元都是一樣的,也就是說生成的字元序列不隨機,所以我們需要把srand((unsigned)time(NULL)); 從for循環中移出放在for語句前面,這樣可以生成隨機的字元序列,而且每次運行生成的字元序列會不同(呵呵,也有可能相同,不過出現這種情況的幾率太小了)。
如果你把srand((unsigned)time(NULL));改成srand(2);這樣雖然在一次運行中產生的字元序列是隨機的,但是每次運行時產生的隨機字元序列串是相同的。把srand這一句從程序中去掉也是這樣。

此外,你可能會遇到這種情況,在使用timer控制項編製程序的時候會發現用相同的時間間隔生成的一組隨機數會顯得有規律,而由用戶按鍵command事件產生的一組隨機數卻顯得比較隨機,為什麼?根據我們上面的分析,你可以很快想出答案。這是因為timer是由計算機時鍾記數器精確控制時間間隔的控制項,時間間隔相同,記數器前後的值之差相同,這樣時鍾取值就是呈線性規律的,所以隨機種子是呈線性規律的,生成的隨機數也是有規律的。而用戶按鍵事件產生隨機數確實更呈現隨機性,因為事件是由人按鍵引起的,而人不能保證嚴格的按鍵時間間隔,即使嚴格地去做,也不可能完全精確做到,只要時間間隔相差一微秒,記數器前後的值之差就不相同了,隨機種子的變化就失去了線性規律,那麼生成的隨機數就更沒有規律了,所以這樣生成的一組隨機數更隨機。這讓我想到了各種晚會的抽獎程序,如果用人來按鍵產生幸運觀眾的話,那就會很好的實現隨機性原則,結果就會更公正。

最後,我總結兩個要點:
1.計算機的偽隨機數是由隨機種子根據一定的計算方法計算出來的數值。所以,只要計算方法一定,隨機種子一定,那麼產生的隨機數就是固定的。
2.只要用戶或第三方不設置隨機種子,那麼在默認情況下隨機種子來自系統時鍾。

❸ 生成隨機數幾種方式

在shell中有一個環境變數RANDOM,它的范圍是0--32767

1、如果我們想要產生0-25范圍內的數,如何做呢?如下:

用這個環境變數對26取模,就可以得到最小是0,最改肆伏大是25的數了。

2、如果想得到1--68范圍內的數,可以這樣
前面可以得到最小為0,最大為67的隨機數,再加上1,很自然的就可以得到最大為1,最小為68的數了。

3、如果想得到6--87范圍內的數。可以這樣

前面可以得到最小為0,最大為81的隨機數,再加上6,很自然的就可以得到最大為87,最小為6的數了。

通過上面三個例子,其它范圍內的數一樣可以用這種方法產生,總結出規律來
可以類推其它范圍內數了

介紹:
1、/dev/random和/dev/urandom是Linux系統中提供的隨機偽設備,這兩雹悄個設備的任務,是提供永不為空的隨機位元組數據流。很多解密程序與安全應用程序(如SSH Keys,SSL Keys等)需要它們提供的隨機數據流。

2、這兩個設備的差異在於:/dev/random的random pool依賴於系統中斷,因此在系統的中斷數不足時,/dev/random設備會一直封鎖,嘗試讀取的進程就會進入等待狀態,直到系統的中斷數充分夠用, /dev/random設備可以保證數據的隨機性。/dev/urandom不依賴系統的中斷,也就不會造成進程忙等待,但是數據的隨機性也不高。

3、dev/urandom 和dev/random,都是產生用不為空的隨機字元流,區別是
/dev/random設備會封鎖,直到系統產生的隨機字元流已經充分夠用,所以耗用時間較長
/dev/urandom設備不會封鎖,數據的隨機程度不高,但是一般情況已經夠用

4、使用/dev/random比使用/dev/urandom產生大量隨機數的速度要慢

通過過濾賽選可以取出隨機數或隨機字母如下
產生隨機字母方式:

NbvFFlhs
[root@centos7 bin]#

產生隨機數字方式

用途:
用來產生偽隨機位元組。隨機數字產生器需要一個seed,先已經說過了,在沒有/dev/srandom系統下的解決方法是自己做一個~/.rnd文件。如果該程序能讓隨機數字產生器很滿意的被seeded。程序寫回一些怪怪的東西回該文件。
用法:

選項說明:
-out file:結果輸出到file中。
-rand file(s):指定隨機數種子文件,多個文件間用分隔符分開,windows用「;」,OpenVMS用「,「,其他系統用「:」。
-base64:輸出結果為BASE64編碼數據。
-hex:輸出核攜結果為16進制數據。
num:隨機數長度。

實例:

可以看見,這12個位元組的隨機數顯示為亂碼,可以對隨機字元串進行base64編碼或用hex格式顯示

通過過濾賽選可以取出隨機數或隨機字母如下
產生隨機字母方式:

產生隨機數字方式

四、應用

字體加顏色
\033[33m 字元 \033[0m [[31m 字元 [[0m
隨機顏色
color= RANDOM%8+31]
\033[${color}m 字元 \033[0m
存放顏色案例的文件
cat /etc/DIR_COLORS

閱讀全文

與偽隨機數生成方法有哪些相關的資料

熱點內容
導泄作用的研究方法 瀏覽:92
生態建設的方法有哪些 瀏覽:570
職位評價技巧和方法 瀏覽:301
有治療近視的方法嗎 瀏覽:745
蟲草花的最佳食用方法煲湯 瀏覽:374
寶雞扶風種植方法 瀏覽:676
目前術後疼痛臨床最常用的方法 瀏覽:967
衣櫃空心橫桿的正確安裝方法 瀏覽:847
梨花燙的製作方法視頻 瀏覽:659
人參的鑒別方法和原理 瀏覽:251
紅米6手機麥克風許可權在哪裡設置方法 瀏覽:452
失眠晚上耳鳴最好的治療方法 瀏覽:271
測定hiv的最簡便方法是選擇題 瀏覽:742
elf冰淇淋妝前膏怎麼使用方法 瀏覽:686
炸雞架子的方法和步驟 瀏覽:152
孕期口臭怎麼治療方法 瀏覽:45
快速冷卻方法 瀏覽:286
蘋果4s的模式在哪裡設置方法 瀏覽:951
24乘205簡便運算方法 瀏覽:341
1萬小時定律訓練方法 瀏覽:604