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 3
0,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
- 乱数の道はまだまだ遠そうだ・・・。