【C++】指定された確率に従って3つの数値のいずれかを生成する関数の実装方法
この記事では、与えられた確率に従って3つの数値(A・B・C)のいずれかを返す関数を、C++で実装する方法を解説します。
問題の概要
ここでは、標準ライブラリの乱数生成関数 rand() を利用します。この関数は一定範囲内の数値を等しい確率(一様分布)で生成するという特徴を持っています。
私たちのタスクは、この一様な乱数を元に、出現確率がそれぞれ P(A)、P(B)、P(C) となる3つの数値 A・B・C のみを返す関数を作成することです。確率の定義より、次の式が成り立ちます。
P(A) + P(B) + P(C) = 1
アルゴリズムの考え方
rand() を使って目的の関数を作るには、「どの数値も同じ確率で出現する」という性質を活用します。ただし、必要なのは P(A) の確率で A を、P(B) の確率で B を得ることです。
そこで、各数値の確率をパーセンテージとして扱います。例えば、P(A) = 1/5 であれば「20%」として考えます。確率の合計は最大100%になるため、まず0から100の間の乱数を1つ生成し、その値がどの区間に属するかに応じて、以下の条件で返す数値を決定します。
- ケース1: 生成された数値が 0〜P(A) の範囲なら → A を返す
- ケース2: 生成された数値が P(A)〜P(A)+P(B) の範囲なら → B を返す
- ケース3: 生成された数値が P(A)+P(B)〜P(A)+P(B)+P(C)(=100%)の範囲なら → C を返す
具体例
次の入力を考えてみましょう。
A = 3 , P(A) = 35% B = 43, P(B) = 50% C = 90, P(C) = 15%
この場合、プログラムは次のように動作します。
- rand関数が 0〜35 の数値を生成した場合 → 3 を返す
- rand関数が 35〜85 の数値を生成した場合 → 43 を返す
- rand関数が 85〜100 の数値を生成した場合 → 90 を返す
実装コード
上記のロジックを実際に実装したプログラムがこちらです。
#include<iostream>
using namespace std;
int randomABC(int A, int B, int C, int PA, int PB, int PC){
int randNumber = rand()%100+1;
if (randNumber <= PA)
return A;
if (randNumber <= (PA+PB))
return B;
else
return C;
}
int main(){
cout<<"Random number between 3, 45, 90 with given probabilities is : "<<randomABC(3, 43, 90, 35, 40, 25);
return 0;
}
出力結果
Random number between 3, 45, 90 with given probabilities is : 3
まとめ
この手法は、一様乱数を確率の境界値と比較することで、任意の確率分布に従う乱数生成を実現するシンプルな方法です。「逆変換法」の簡易版とも言え、選択肢が4つ以上の場合にも同じ要領で拡張できます。
なお、実用的なプログラムでは、実行のたびに異なる結果を得るために、main() の冒頭で srand(time(NULL)) を呼び出して乱数列のシードを初期化しておくことをおすすめします。
-
C++で指定範囲内のMで割り切れる数を数える方法
3つの整数 A、B、M が与えられます。A と B は数値の範囲 [A, B] を定義し、目的はこの範囲内に存在する M で割り切れる数の個数を求めることです。基本的な考え方は、i = A から順に最初の M の倍数まで走査し、i % M == 0 が成立するたびにカウントを増やしていくというものです。その後、i ≤ B である限り i を増加させながら同様の判定を繰り返します。具体例で確認してみましょう。入力例A=11, B=20, M=5出力指定範囲内でMで割り切れる数の個数: 2説明範囲 [11, 20] 内で 5 で割り切れる数は 15 と 20 のみです。したがって、答えは 2 とな
-
【C++】バックトラッキングでグリッドの8つのマスに1〜8の数字を条件付きで配置する方法
この記事では、図の中にある8つの丸(マス)に「1」から「8」までの数字を、「数列上で隣り合う数字同士がグリッド上でも隣接しない」という条件を満たすように配置する問題を、C++で解く方法を解説します。問題の概要たとえば、入力として次のような3×4のグリッドが与えられたとします。「0」は使用しないマス、「-1」はまだ数字が置かれていない空きマスを表します。0-1-10-1-1-1-10-1-10この場合の出力は次のようになります。 3 5 7 1 8 2 4 6この結果では、たとえば「1」と「2」、「7」と「8」のように数列で連続する数字が、グリッド上で上下左右・斜めに隣り合わないように配置