高校数学をプログラミングで解く(数学B編)「4-4 同時分布」
マガジンリスト > 数学B編 4.確率分布と統計的な推測 > 4-4 同時分布
はじめに
今回は、数学Bで学ぶ「同時分布」について、2つの確率変数$${X,Y}$$に対する同時分布を求めるプログラムを作成します。
同時分布
まず、同時分布について解説しておきます。
ある試行結果により値の定まる2つの確率変数$${X,Y}$$に対し、$${P(X=x_i, Y=y_j)=p_{ij}}$$とするとき、$${(x_i, y_j)}$$と$${p_{ij}}$$の対応を$${X}$$と$${Y}$$の同時分布という。
$$
\begin{array}{c||cccc|c}
\hline
X \backslash Y & y_1 & y_2 & \cdots & y_m & \mathrm{計} \\
\hline \hline
x_1 & p_{11} & p_{12} & \cdots & p_{1m} & p_1 \\
x_2 & p_{21} & p_{22} & \cdots & p_{2m} & p_2 \\
\vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\
x_n & p_{n1} & p_{n2} & \cdots & p_{nm} & p_n \\
\hline
\mathrm{計} & q_{1} & q_{2} & \cdots & q_{m} & 1 \\
\hline
\end{array}
$$
同時分布を計算する
今回は次のような問題を考えてみます。
問題
2枚の硬貨を同時に投げる試行を2回行う。1回目の試行で表の出る枚数を$${X}$$、2回目の試行で表の出る枚数を$${Y}$$とするとき、$${X}$$と$${Y}$$の同時分布を求めよ。
アルゴリズム設計
今回は、2枚の硬貨を同時に投げる試行を2回行うので、計4枚の硬貨の裏表の出方を考えればよいことがわかります。つまり、「1回目の試行での1枚目の硬貨の裏表の2通り×1回目の試行での2枚目の硬貨の裏表の2通り×2回目の試行での1枚目の硬貨の裏表の2通り×2回目の試行での2枚目の硬貨の裏表の2通り」で計16通りの出方について、順に1回目の試行で表の出た枚数と2回目の試行で表の出た枚数とを数えることでそれぞれの場合の数を算出して最後にすべての出方16通りで割って、確率分布を算出することにします。
具体的には、変数$${c_{11}}$$を準備し、1回目の試行の1枚目の硬貨に表が出たら$${c_{11}}$$に1を与え、裏が出たら$${c_{11}}$$に0を与えるようにします。同様に、1回目の試行の2枚目の硬貨に対して変数$${c_{12}}$$、2回目の試行の1枚目の硬貨に対して$${c_{21}}$$、2回目の試行の2枚目の硬貨に対して$${c_{22}}$$をそれぞれ準備し、表が出たら1を与え、裏が出たら0を与えるようにします。このように変数を設定すると、1回目の試行で表の出る枚数は
$$
x = c_{11}+c_{12}
$$
で計算することができ、また、2回目の試行で表の出る枚数は
$$
y = c_{21}+c_{22}
$$
で計算することができます。
プログラム
では、$${X}$$と$${Y}$$の同時分布を求めるプログラムを作成していきます。
// 2枚の硬貨を同時に投げる試行を2回行う。
// 1回目の試行で表の出る枚数をX、2回目の試行で表の出る枚数をYとするとき、
// XとYの同時分布を求める
void setup(){
// 2回の試行でのすべての場合の数
int all_event_num = 2*2*2*2;
// 場合の数
int[][] nc = {{0,0,0},{0,0,0},{0,0,0}};//new int[3][3];
// 同時分布P
float[][] p = new float[3][3];
int x; // 1回目の試行で表が出た枚数
int y; // 2回目の試行で表が出た枚数
for(int c11=0; c11<=1; c11++){ // 1回目の試行での1枚目の裏表
for(int c12=0; c12<=1; c12++){ // 1回目の試行での2枚目の裏表
for(int c21=0; c21<=1; c21++){ // 2回目の試行での1枚目の裏表
for(int c22=0; c22<=1; c22++){ // 2回目の試行での2枚目の裏表
x = c11+c12; // 1回目の試行での表の数
y = c21+c22; // 2回目の試行での表の数
nc[x][y] = nc[x][y] + 1; // x,yとなる場合の数を数える
}
}
}
}
// XとYの同時分布を算出する
for(int i=0; i<=2; i++){
for(int j=0; j<=2; j++){
p[i][j] = (float)nc[i][j] / all_event_num;
}
}
// 算出した同時分布をコンソールに出力
for(int i=0; i<=2; i++){
println(p[i][0],p[i][1],p[i][2]);
}
}
ソースコード1 $${X}$$と$${Y}$$の同時分布を求めるププログラム
このソースコードを、Processingの開発環境ウィンドウを開いて(スケッチ名を「SimultaneousDistribution_twoCoins」としています)、テキストエディタ部分に書いて実行します。
図1のように、確率変数$${X}$$と$${Y}$$の同時分布を
0.0625 0.125 0.0625
0.125 0.25 0.125
0.0625 0.125 0.0625
のようにコンソールに出力します。なお、これらの値は表で表すと
$$
\begin{array}{c||ccc|c}
\hline
X \backslash Y & 0 & 1 & 2 & \mathrm{計} \\
\hline \hline
0 & 1/16 & 1/8 & 1/16 & 1/4 \\
1 & 1/8 & 1/4 & 1/8 & 1/2 \\
2 & 1/16 & 1/8 & 1/16 & 1/4 \\
\hline
\mathrm{計} & 1/4 & 1/2 & 1/4 & 1 \\
\hline
\end{array}
$$
となっています。
プログラムの解説「2次元配列」
今回、同時分布やそれに関連した場合の数を表す変数として、2次元配列を導入しました。この2次元配列について解説しておきます。
配列については、記事『高校数学をプログラミングで解く(準備編)「2-4 配列」』で解説しています。復習しておくと、配列の宣言と領域確保は、
void setup(){
int[] a = int[3];
}
と行い、配列への値の代入は、
void setup(){
int[] a = new int[3];
a[0] = 3;
a[1] = 1;
a[2] = 4;
}
のように配列の各要素に代入する方法や、
void setup(){
int[] a = {3,1,4};
}
のように1行で行う方法がありました。そして、配列の要素はa[0]のように「配列名[要素番号]」の形で1つの変数として利用することができます。
2次元配列も配列と同じように扱うことができます。違いは2つの要素番号を指定するところです。つまり、2次元配列の宣言と領域確保は、
void setup(){
int[][] a = int[3][3];
}
のように、2つの要素番号の要素数を与えて行い、2次元配列への値の代入は、
void setup(){
int[][] a = new int[3][3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
a[2][0] = 7;
a[2][1] = 8;
a[2][2] = 9;
}
のように2次元配列の各要素に代入する方法でもできますし、
void setup(){
int[] a = {{1,2,3},{4,5,6},{7,8,9}};
}
のように1行で行う方法でもできます。そして、2次元配列の要素はa[0][1]のように「配列名[1つ目の要素番号][2つ目の要素番号]」の形で1つの変数として利用することができます。
今回は、同時分布での確率が$${p_{ij}}$$のように2つの添え字を指定して表されるものであるため、2次元配列を利用したわけです。
まとめ
今回は、数学Bで学ぶ「同時分布」について、2つの確率変数$${X,Y}$$に対する同時分布を求めるプログラムを作成しました。
同時分布で扱う確率は$${p_{ij}}$$のように2つの添え字に依存する形が表されます。そのため、今回はこの同時分布を表すために、2次元配列を利用しました。2次元配列は以前『高校数学をプログラミングで解く(準備編)「2-4 配列」』で解説した配列と、2つの要素番号を指定するところで違いはありますが、それ以外はほぼ同じように扱うことができます。
今回のように、用途に合わせて配列や2次元配列を使えるようになると、プログラミングの幅が広がっていきますので、このような使い分けにも慣れていってもらえればと思います。
参考文献
改訂版 教科書傍用 スタンダード 数学B(数研出版、ISBN9784410209468)