【第1部】C言語(K&R検証)編
0012.擬似乱数の発生
ソース紹介
CPPファイルに記述
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
unsigned long next_num = 1;
/*
0から32767の間の範囲の擬似乱数を発生させる
*/
int Rand() {
next_num = next_num * 1103515245 + 12345;
return (unsigned int)(next_num / 65526) % 32768;
}
/*
rand の種を設定
*/
void Srand(unsigned int seed) {
next_num = seed;
}
/*
乱数のテスト
*/
int main()
{
//乱数のseedを初期化
Srand((unsigned int)time(nullptr));
int arr[100];
//配列の初期化
for (int i = 0; i < 100; i++) {
arr[i] = 0;
}
//乱数を発生させ、カウンタをインクリメント
for (int i = 0; i < 1000000; i++) {
arr[Rand() % 100]++;
}
//結果出力。各数値が何個づつ発生したか確認
for (int i = 0; i < 100; i++) {
cout << i << '\t' << arr[i] << endl;
}
return 0;
}
出力
0 9947
1 10081
2 10152
3 10086
4 10198
5 9905
6 10081
7 9848
8 9955
9 9907
10 10040
11 9957
12 9995
13 10143
14 10065
15 10079
16 9953
17 9916
18 9877
19 10120
20 10077
21 9994
22 10080
23 10076
24 9864
25 9900
26 10157
27 10005
28 10054
29 10037
30 10009
31 9892
32 10010
33 10014
34 10044
35 10099
36 10037
37 10089
38 10000
39 10123
40 10067
41 10158
42 10096
43 10003
44 9967
45 9972
46 10097
47 10034
48 10008
49 10090
50 10019
51 10009
52 10120
53 10041
54 9936
55 9923
56 9982
57 9914
58 9847
59 9990
60 9972
61 10147
62 9998
63 10088
64 9960
65 9932
66 9937
67 10031
68 9819
69 9995
70 9998
71 9900
72 9842
73 9932
74 9997
75 9982
76 9978
77 9842
78 9958
79 9849
80 9890
81 10203
82 9811
83 9982
84 9934
85 10022
86 9873
87 10198
88 9968
89 10054
90 9911
91 10132
92 9959
93 9952
94 9901
95 9976
96 9942
97 9973
98 9969
99 10054
サンプル説明
このテストは
1000000回(百万回)乱数を発生させ、それぞれを
100で割ったあまりが、どのように分布されているかを確認しています。
こうしてみると、分布的には、ほどほどばらけていると思います。ただ、どのような順番で出きているかはテストしてないので、それは各自やってみるとよいと思います。
ここで紹介されている
擬似乱数発生アルゴリズムは
線形合同法を使ってます。
next_num = next_num * 1103515245 + 12345;
のように固定値をもとに計算しています(初期化に使用するSEEDはtime()でとってきますが)。
擬似乱数の計算方法はいろんな人が、ブログなど書いているので、調べてみると面白いでしょう。
K&Rでの記述
元になったのは
第2章:データ型・演算子・式に記述されています。
型変換の説明のところです。