以下說明之方法,與平方取中法均有相似之處,其重大缺點都一樣,最後容易面臨退化之窘境。
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; }
全站熱搜