K&Rを読もう(26) randの写経。
疑似乱数がこんなに単純なアルゴリズムで出来ているとは・・・。もっと単純にしてみた。
適当なa、p、qを選んで、
ap + q = a'
とする。次にa'をaに代入する。で、余りを取る。
後はニュートン法のように繰り返すだけ。
#include <stdio.h> #include <stdlib.h> unsigned long int next = 1; #define RAND_MAX_COPY 10 int rand_copy(void) { next = next * 3 + 1; return (unsigned int) next % RAND_MAX_COPY; } int main(void) { int i; for (i = 0; i < 10; i++) printf("%10d %d\n", next, rand_copy()); exit(EXIT_SUCCESS); }
わかりやすいように、nextを3倍して1を足して10の余りを取りました。
実行結果は・・・。
4 4
13 3
40 0
121 1
364 4
1093 3
3280 0
9841 1
29524 4
88573 30,1,3,4しか出ませんね。。。。(汗
- 桁が溢れたときに、nextが0になってしまう値を選ぶと一定の値になってしまう。
- K&Rでは、next % RAND_MAXを,next / (RAND_MAX * 2) % RAND_MAXとしてた。理由がイマイチわからん。
- わかった。Wikipediaより引用。「十の位から十万の位までを採用することとする。」下の桁を切捨てるために割ったのか!!おぉぉぉぉ。わかった!!
- 「0,1,3,4しか出ない」というのが解消されそうだ。
10の位を採用してみる。
4 0
13 1
40 4
121 2
364 6
1093 9
3280 8
9841 4
29524 2
88573 7おぉぉぉぉぉ。疑似乱数だ!!
疑似乱数の簡単な仕組みがわかった!!
参考
- 擬似乱数 - Wikipedia
- 乱数の道はまだまだ遠そうだ・・・。