VC++中的偽隨機(jī)數(shù)

字號(hào):

為追求真正的隨機(jī)序列,人們?cè)捎煤芏喾N原始的物理方法用于生成一定范圍內(nèi)滿足精度(位數(shù))的均勻分布序列,其缺點(diǎn)在于:速度慢、效率低、需占用大量存儲(chǔ)空間且不可重現(xiàn)等。為滿足計(jì)算機(jī)模擬研究的需求,人們轉(zhuǎn)而研究用算法生成模擬各種概率分布的偽隨機(jī)序列。偽隨機(jī)數(shù)是指用數(shù)學(xué)遞推公式所產(chǎn)生的隨機(jī)數(shù)。從實(shí)用的角度看,獲取這種數(shù)的最簡(jiǎn)單和最自然的方法是利用計(jì)算機(jī)語言的函數(shù)庫提供的隨機(jī)數(shù)發(fā)生器。典型情況下,它會(huì)輸出一個(gè)均勻分布在0和1區(qū)間內(nèi)的偽隨機(jī)變量的值。其中應(yīng)用的最為廣泛、研究最徹底的一個(gè)算法即線性同余法。
    線性同余法LCG(Linear Congruence Generator)
    選取足夠大的正整數(shù)M和任意自然數(shù)n0,a,b,由遞推公式:
    ni+1=(af(ni)+b)mod M i=0,1,…,M-1
    生成的數(shù)值序列稱為是同余序列。當(dāng)函數(shù)f(n)為線性函數(shù)時(shí),即得到線性同余序列:
    ni+1=(a*ni+b)mod M i=0,1,…,M-1
    以下是線性同余法生成偽隨機(jī)數(shù)的偽代碼:
    Random(n,m,seed,a,b)
    {
    r0 = seed;
    for (i = 1;i<=n;i++)
    ri = (a*ri-1 + b) mod m
    }
    其中種子參數(shù)seed可以任意選擇,常常將它設(shè)為計(jì)算機(jī)當(dāng)前的日期或者時(shí)間;m是一個(gè)較大數(shù),可以把它取為2w,w是計(jì)算機(jī)的字長;a可以是0.01w和0.99w之間的任何整數(shù)。
    應(yīng)用遞推公式產(chǎn)生均勻分布隨機(jī)數(shù)時(shí),式中參數(shù)n0,a,b,M的選取十分重要。
    例如,選取M=10,a=b =n0=7,生成的隨機(jī)序列為{6,9,0,7,6,9,……},周期為4。
    取M=16,a=5,b =3,n0=7,生成的隨機(jī)序列為{6,1,8,11,10,5,12,15,14,9,0,3,2,13,4,7,6,1……},周期為16。
    取M=8,a=5,b =1,n0=1,生成的隨機(jī)序列為{6,7,4,5,2,3,0,1,6,7……},周期為8。
    Visual C++中偽隨機(jī)數(shù)生成機(jī)制
    用VC產(chǎn)生隨機(jī)數(shù)有兩個(gè)函數(shù),分別為rand(void)和srand(seed)。rand()產(chǎn)生的隨機(jī)整數(shù)是在0~RAND_MAX之間平均分布的,RAND_MAX是一個(gè)常量(定義為:#define RAND_MAX 0x7fff)。它是short型數(shù)據(jù)的值,如果要產(chǎn)生一個(gè)浮點(diǎn)型的隨機(jī)數(shù),可以將rand()/1000.0,這樣就得到一個(gè)0~32.767之間平均分布的隨機(jī)浮點(diǎn)數(shù)。如果要使得范圍大一點(diǎn),那么可以通過產(chǎn)生幾個(gè)隨機(jī)數(shù)的線性組合來實(shí)現(xiàn)任意范圍內(nèi)的平均分布的隨機(jī)數(shù)。
    其用法是先調(diào)用srand函數(shù),如
    srand( (unsigned)time( NULL ) )
    這樣可以使得每次產(chǎn)生的隨機(jī)數(shù)序列不同。如果計(jì)算偽隨機(jī)序列的初始數(shù)值(稱為種子)相同,則計(jì)算出來的偽隨機(jī)序列就是完全相同的。要解決這個(gè)問題,需要在每次產(chǎn)生隨機(jī)序列前,先指定不同的種子,這樣計(jì)算出來的隨機(jī)序列就不會(huì)完全相同了。以time函數(shù)值(即當(dāng)前時(shí)間)作為種子數(shù),因?yàn)閮纱握{(diào)用rand函數(shù)的時(shí)間通常是不同的,這樣就可以保證隨機(jī)性了。也可以使用srand函數(shù)來人為指定種子數(shù)。