メルセンヌ・ツイスタで乱数の生成範囲を指定したいのですが
以下の方法(1),(2)以外でもっと厳密に一様乱数を生成できる方法がわかる方いますか?
(1)
int n;
n = genrand_int32() % 100;
(2)
int n;
n = (genrand_real3() * 100);
上記の方法では一様乱数ではなく、必ず偏りが生じてしまいます。
分かる方いましたら宜しくお願いします。
メルセンヌ・ツイスタの乱数生成範囲指定
Re: メルセンヌ・ツイスタの乱数生成範囲指定
この方針では偏りが生じます。(例えば0~5の値が出る乱数を用いて、0~3の乱数を出すことを考えるとわかる)
偏りが生じないようにするには、半端な部分の値が出たらそれを棄却して乱数を取得しなおすと良いです。
参照:いつからその方法で偏りのない乱数が得られると錯覚していた? - アスペ日記
#include <stdio.h>
#include "mt19937ar.h"
unsigned int rand_uniform(unsigned int max) {
/* 「余り」の数を求める */
unsigned int reject=0xffffffff%max;
unsigned int randnum;
reject=(reject+1)%max;
do {
randnum=genrand_int32();
} while(randnum<reject);
return (unsigned int)((double)(randnum-reject)*max/(4294967296.0-reject));
}
int main(int argc,char* argv[]) {
int i;
unsigned int max=10;
if(argc>=2)sscanf(argv[1],"%u",&max);
for(i=0;i<100;i++) {
printf("%u\n",rand_uniform(max));
}
return 0;
}
上にあげたサイトのプログラムの、rand()をgenrand_int32()に、RAND_MAXを0xffffffffuに置き換えたものも利用できます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)