見出し画像

高校数学をプログラミングで解く(数学A編)「1-7 反復試行の確率」

割引あり

マガジンリスト > 数学A編 1.場合の数と確率 > 1-7 反復試行の確率


はじめに

今回は、数学Aで学ぶ「反復試行の確率」について、反復試行の確率を計算するプログラムを作成します。

反復試行の確率

まず、反復試行の確率について復習しておきます。

反復試行の確率
1回の試行で事象$${A}$$が起こる確率を$${p}$$とする。この試行を$${n}$$回繰り返しおこなうとき、事象$${A}$$がちょうど$${r}$$回起こる確率は、

$$
{}_nC_r p^r(1-p)^{n-r}
$$

$${ {}_nC_r }$$は異なる$${n}$$個のものから$${r}$$個を取る組合せの総数を表します。

反復試行の確率を計算する

今回は次のような問題を考えてみます。

問題
1個のさいころを3回投げるとき、2の目がちょうど2回出る確率を求めよ。

この問題は、1個のさいころを1回投げるときに2の目が出る確率が$${1/6}$$となるので、3回投げて2の目がちょうど2回出る確率は

$$
{}_3C_2 \left( \frac{1}{6} \right)^2 \left( 1-\frac{1}{6} \right)^{3-2} = \frac{3 \cdot 2}{2 \cdot 1} \cdot \left( \frac{1}{6} \right)^2 \left( \frac{5}{6} \right) = \frac{5}{72} = 0.069\.{4}
$$

と計算することができます。

アルゴリズム設計

今回は1個のさいころを1回投げるときに2の目が出る確率は$${1/6}$$となることを与えることにします。また、計算式は反復試行の確率の式をそのまま利用します。つまり、組合せの総数$${ {}_nC_r }$$、さいころを$${r}$$回投げて常に2の目が出る確率、そしてさいころを$${n-r}$$回投げて常に2の目以外が出る確率をそれぞれ計算して掛け合わせることで、反復試行の確率を計算します。
なお、組合せの総数$${ {}_nC_r }$$の計算については、別の記事『高校数学をプログラミングで解く(数学A編)「1-4 組合せ」』で解説していますので、詳細はそちらをご覧ください。

プログラム

では、反復試行の確率を計算するプログラムを作成していきます。

// 1個のさいころを3回投げるとき、2の目がちょうど2回出る確率
void setup(){

  float p = 1.0/6.0; // 2の目が出る確率
  int n = 3; // 試行の回数
  int r = 2; // 2の目が出る回数
  // 反復試行の確率
  float P = combination(n,r) * pow(p, r) * pow(1.0-p, n-r);
 
  println(P); // 確率をコンソールに出力
}

// 異なるn個のものからr個を取る組合せの総数
int combination(int n, int r){
  
  int p = 1; // 組合せの総数の分子
  int q = 1; // 組合せの総数の分母
  for(int i=0; i<r; i++){ 
    p = p * (n-i);
    q = q * (r-i);
  }
  int c = p / q; // 組合せの総数を計算

  return c; // 組合せの総数を出力
}

ソースコード1 反復試行の確率を計算するプログラム

このソースコードを、Processingの開発環境ウィンドウを開いて(スケッチ名を「probability_ThreeDice」としています)、テキストエディタ部分に書いて実行します。

図1 スケッチ「probability_ThreeDice」の実行結果

図1のように、1個のさいころを3回投げるとき、2の目がちょうど2回出る確率「0.06944445」($${=5/72}$$ )をコンソールに出力します。

プログラムの解説

今回のプログラム(ソースコード1)のポイントは、反復試行の確率$${{}_nC_r p^r(1-p)^{n-r}}$$を計算している部分

float P = combination(n,r) * pow(p, r) * pow(1.0-p, n-r);

です。この式では、Processing に用意されているべき乗を計算するための pow 関数と自作した組合せの総数を計算する関数 combination を利用しています。以下では、これらの関数の解説と、関連した概念としてスコープについての説明を行います。

プログラムの解説1「pow 関数の利用」

一般に、プログラミング言語には、さまざまな便利な関数が用意されています。今回利用しているプログラミング言語 Processing においても、もちろん便利な関数を利用することができます。
今回のプログラム(ソースコード1)では、反復試行の確率の式$${{}_nC_r p^r(1-p)^{n-r}}$$のべき乗の部分$${p^r}$$及び$${(1-p)^{n-r}}$$を計算するために、Processing で用意されている pow 関数を利用しています。

pow(p, r);

pow 関数は2つの浮動小数点数型の引数を取り、順に
p : べき乗の底 float型
r : べき指数 float型
となります。返り値は、$${p^r}$$(float型)を返します。具体的に利用例($${2^3}$$を計算するプログラム)を以下に示します。

// べき乗を計算する関数powのテスト
void setup(){

  float p = 2.0; // 底
  float r = 3.0; // 指数
  float power = pow(p, r); // べき乗の値を求めてpowerに代入
  
  println(power); // べき乗の値をコンソールに出力
}

ソースコード2 pow関数の利用例

このソースコードを、Processing の開発環境ウィンドウを開いて(スケッチ名を「pow_test」としています)、テキストエディタ部分に書いて実行します。

図2 スケッチ「pow_test」の実行結果

図2のように、「8.0」($${=2^3}$$)をコンソールに出力します。pow 関数を利用することで、べき乗が計算できることがわかります。

プログラムの解説2「組合せの総数を計算する関数」

プログラムの解説1の冒頭で、プログラミング言語にはさまざまな便利な関数が用意されており、それらを利用してプログラムを作ることができることを紹介しました。
プログラミング言語では用意された関数だけではなく、自身で関数を作成して利用することができます。今回のプログラムでは組合せの総数$${{}_nC_r}$$を関数にして利用しています。これについて解説します。
別の記事『高校数学をプログラミングで解く(数学A編)「1-4 組合せ」』で、組合せの総数を計算するプログラムを作りました。具体的には、$${{}_7C_3}$$を計算するプログラムでした。

// 異なるn個のものからr個を取る組合せの総数
void setup(){
  
  int n = 7;
  int r = 3;
  int p = 1; // 組合せの総数の分子
  int q = 1; // 組合せの総数の分母
  for(int i=0; i<r; i++){
    p = p * (n-i);
    q = q * (r-i);
  }
  int c = p / q; // 組合せの総数を計算
  println(c); // 組合せの総数をコンソールに出力
}

ソースコード3 組合せの総数$${{}_7C_3}$$を計算するプログラム

このプログラムをベースにして組合せの総数を計算する部分を関数にしていきます。その前に作成する関数の一般的な形を示しておきます。

// 関数の一般的な形
datatype_0 function_name( // 1. 関数名
  datatype_1 variable_1, //2. 1つ目の引数
  datatype_2 variable_2, //2. 2つ目の引数
  …
  datatype_n variable_n // 2. n個目の引数
){
  // 3. “{“と”}”の間に、この関数が行う処理を記載
  return value; // 3. 関数のデータ型と一致する値(value)を返す
}

ソースコード4 関数の一般的な形

  1. 最初に関数名(function_name)を与えます。その際、関数名の左側に関数のデータ型(datatype_0)を記載します。

  2. 関数名の右側に“(“と”)”を記載します。その間に、関数の引数を記載します。引数は複数記載することができ、引数同士はカンマ”,”で区切ります。1つの引数は「データ型 変数名」(datatype variable)の形で与えます。なお、引数として与えた変数は、以下の3.で説明する関数の処理の中で宣言することなしに利用することができます。

  3. “)”の右側に、”{“と”}”を記載します。その間に、この関数が行う処理を記載していきます。処理の最後に、処理の結果を”return”の右側に与えます。これを「返り値」と呼びます。返り値は関数のデータ型と一致する値になります。

それでは、組合せの総数$${{}_nC_r}$$を関数にしていきます。

  1. 関数名は「組合せ」の英語表記「combination」とします。$${{}_nC_r}$$の値が整数となりますので、関数のデータ型はint型にします。

  2. また、2つの整数$${n}$$と$${r}$$を決めれば$${{}_nC_r}$$の値が決まりますので、関数の引数は、int型の変数 n とint型の変数 r の2つを用意します。

  3. 処理はソースコード3をベースにして記述します。返り値はソースコード3でコンソールに出力していた値をそのまま利用します。

// 異なるn個のものからr個を取る組合せの総数
int combination(int n, int r){
  
  int p = 1; // 組合せの総数の分子
  int q = 1; // 組合せの総数の分母
  for(int i=0; i<r; i++){ 
    p = p * (n-i);
    q = q * (r-i);
  }
  int c = p / q; // 組合せの総数を計算

  return c; // 組合せの総数を返す
}

ソースコード5 組合せの総数$${{}_nC_r}$$を計算する関数

では、この関数を利用して、$${{}_7C_3}$$を計算してみます。結果をコンソールに出力します。

// 組合せの総数を計算する関数の利用例
void setup(){
  
  int n = 7;
  int r = 3;
  int c = combination(n, r); // 組合せの総数を計算する関数を利用
  println(c); // 組合せの総数をコンソールに出力
}

// 異なるn個のものからr個を取る組合せの総数
int combination(int n, int r){
  
  int p = 1; // 組合せの総数の分子
  int q = 1; // 組合せの総数の分母
  for(int i=0; i<r; i++){ 
    p = p * (n-i);
    q = q * (r-i);
  }
  int c = p / q; // 組合せの総数を計算

  return c; // 組合せの総数を出力
}

ソースコード6 関数の利用例

作成した関数は、他の関数(今回は setup 関数)の中で

int n = 7;
int r = 3;
int c = combination(n, r);

と具体的な値を引数に与えて記述することで利用することができます。これを「関数を呼び出す」と言います。関数を呼び出すと、その関数は具体的な処理を行い、その結果を返り値として返します。今回はその返り値をint型の変数 c に代入しています。なお、関数自体は setup 関数の下などに記述しておきます(ソースコード6参照)。

ソースコード6を、Processingの開発環境ウィンドウを開いて(スケッチ名を「combination_function」としています)、テキストエディタ部分に書いて実行します。

図3 スケッチ「combination_function」の実行結果

図3のように、「35」($${={}_7C_3}$$)をコンソールに出力します。作成した関数が正しく動いていることがわかります。

プログラムの解説3「スコープについて」

関数を作成することができるようになったので、ここで変数に関する「スコープ」について説明しておきます。
ソースコード6をみると、変数 n, r, c を setup 関数の中と combination 関数の中と両方に利用しています。これらの変数は同じ名前にはなっていますが、異なる変数として扱われています。それは、スコープが異なっているからです。つまり、変数の宣言をどこで行っているかによってその変数の利用範囲が決まります。
一般に、”{“と”}”の間で宣言されている変数はその”{“と”}”の間でのみ有効な変数となります。これを「スコープ」と呼んでいます。例えば、ソースコード 6の setup 関数の”{“と”}”の間で宣言されている変数 n, r, c は、setup 関数の”{“と”}”の間でのみ有効な変数になります。一方、ソースコード6のcombination 関数の引数 n, r や combination 関数の”{“と”}”の間で宣言されている変数 c は、combination関数の”{“と”}”の間でのみ有効な変数になります。そのため、変数 n, r, c は setup 関数の中と combination 関数の中とで異なる変数となるわけです。

まとめ

今回は、数学Aで学ぶ「反復試行の確率」について、反復試行の確率を計算するプログラムを作成しました。
プログラムのポイントは、反復試行の確率$${{}_nC_r p^r(1-p)^{n-r}}$$を計算するところです。今回は、べき乗$${p^r}$$を計算するためにProcessingで用意されている関数 pow を利用し、組合せの総数$${{}_nC_r}$$については関数 combination を自作して利用しました。
また、今回は変数に関する概念「スコープ」についても説明しました。スコープは、今後プログラムを作成していく上で重要になってきますが、もしこのスコープの概念がわかりにくいようであれば、最初は宣言を行う変数の名前をすべて異なるものにしておいて、慣れてくれば、スコープを意識して変数の宣言をするようにした方がよいでしょう。焦らずに一つ一つ理解していってください。

参考文献

改訂版 教科書傍用 スタンダード 数学A(数研出版、ISBN9784410209277)


演習問題

1枚の硬貨をAさんは 4 回、Bさんは 5 回投げる。このとき、表の出る回数がAさんは 3 回、Bさんは 2 回である確率を求め、その結果をコンソールに出力するプログラムを作成してください。

演習問題の解答例

ここから先は

425字 / 1画像 / 1ファイル

この記事が気に入ったらサポートをしてみませんか?