teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

a

2018/10/10 09:45

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -60,4 +60,76 @@
60
60
  ## 他のアルゴリズム
61
61
 
62
62
  正規分布を生成するアルゴリズムは他にもあるようです。
63
- いろいろなアルゴリズムの実装が提供されている [Github](https://github.com/miloyip/normaldist-benchmark) を見つけたので、見てみると面白いかもしれません。
63
+ いろいろなアルゴリズムの実装が提供されている [Github](https://github.com/miloyip/normaldist-benchmark) を見つけたので、見てみると面白いかもしれません。
64
+
65
+ ## 追記 グラフの生成方法について
66
+
67
+ 以下のコードでテキストファイルに出力して、Python で読み込んで seaborn というライブラリでプロットしました。
68
+ Cだけでプロットする場合は gunplot とか使うことになるのでしょうけど、それでも結構面倒くさいです。Python だと1行できれいなグラフが出力できます。
69
+
70
+ ```cpp
71
+ #include <fstream>
72
+ #include <math.h>
73
+ #include <stdio.h>
74
+ #include <stdlib.h>
75
+
76
+ /**
77
+ @brief [-1, 1] の一様分布に従う乱数を生成する。
78
+ @return [-1, 1] の一様分布に従う乱数
79
+ */
80
+ double urand()
81
+ {
82
+ return (double)rand() / RAND_MAX * 2. - 1.;
83
+ }
84
+
85
+ double nrand()
86
+ {
87
+ // 1度に2個の正規分布に従う値 r1, r2 が得られるので
88
+ // 生成したときは r1、次に呼び出したときは r2 を返す。
89
+ static int sw = 0; // switch 用のフラグ
90
+ static double r1, r2, s;
91
+
92
+ if (sw == 0) {
93
+ sw = 1;
94
+ // (x, y) \in [-1, 1]^2 を満たす点をランダムに選ぶ。
95
+ do {
96
+ r1 = urand();
97
+ r2 = urand();
98
+ s = r1 * r1 + r2 * r2;
99
+ } while (s > 1.0 || s == 0.0);
100
+
101
+ // 正規分布に従う点に変換する。
102
+ s = sqrt(-2. * log(s) / s);
103
+ return r1 * s;
104
+ }
105
+ else {
106
+ sw = 0;
107
+ return r2 * s;
108
+ }
109
+ }
110
+
111
+ int main()
112
+ {
113
+ int seed = 1234567;
114
+
115
+ srand(seed);
116
+ std::ofstream ofs("values.csv");
117
+ for (int i = 0; i < 1000; i++)
118
+ ofs << nrand() << std::endl;
119
+ }
120
+ ```
121
+
122
+ ファイルを読み込んで、出力する。
123
+
124
+ ```python
125
+ import seaborn as sns
126
+ import matplotlib.pyplot as plt
127
+ import numpy as np
128
+
129
+ array = np.loadtxt('values.csv')
130
+ print(array.shape)
131
+
132
+ sns.set()
133
+ ax = sns.distplot(array)
134
+ plt.show()
135
+ ```