以下說明之方法,與平方取中法均有相似之處,其重大缺點都一樣,最後容易面臨退化之窘境。

Midproduct Method (中間乘積法)

中間乘積法初始時,亂數種子必須設二個 s1, s2,假設欲生成 0~32767 之亂數 (15 位),乃是將 s1*s2 後之結果 (30 位數),取其中間 15 位數 (32 位元可拆成 9 15 8)。 C 語言大致如下所示

#include <stdio.h>
#include <time.h>

int seed1, seed2;

void MidProduct_srand(int s1, int s2)
{
    seed1=s1;
    seed2=s2;
}

int MidProduct_rand()
{
    int ret = ((seed1 * seed2) & 0x007fffff) >> 8;
    seed1 = seed2;
    seed2 = ret;
    return ret;
}

int main()
{
    int i=0;
    MidProduct_srand((int)time(NULL), (int)time(NULL));
    for(i=0; i!=20; ++i) printf("%d ", MidProduct_rand());
    return 0;
}

 

使用時必須注意一件事,事實上那份 MidProduct_srand 第二個種子,不該連續直接調用 time(NULL) ,因 time 函式只為一秒更新一次,另一個參數可由 getpid() 方式取得。

另, MidProduct 方式,在取得 [0,1) 之浮點亂數時,大多會直接傳回小數值,如產生結果為 123456,整數取 2345,而小數部份便為 0.2345;但這種方式較適合 10 進位處理,若以上述 binary 方式,仍再除以 RAND_MAX + 1 為方便。這種方式最後仍會趨近退化之結果。

Constant multiplier method (固定乘數法)

固定乘數法與上述之中間乘積法相似,只是其中一個乘數固定為 K 。其實這方面和後面所說的 LCG 頗為相似。在此選擇其中之乘數 K = 16807,欲產生 0~32767 之亂數如下

#include <stdio.h>
#include <time.h>

int seed;

void ConstMulti_srand(int s)
{
    seed = s;
}

int ConstMulti_rand()
{
    const int K = 16807;
    int ret = ((K * seed) & 0x007fffff) >> 8;
    seed = ret;
    return ret;
}

int main()
{
    int i=0;
    ConstMulti_srand((int)time(NULL));
    for(i=0; i!=20; ++i) printf("%d ", ConstMulti_rand());
    return 0;
}

 

edisonx 發表在 痞客邦 PIXNET 留言(0) 人氣()