C++
 Computer >> コンピューター >  >> プログラミング >> C++

【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)) を呼び出して乱数列のシードを初期化しておくことをおすすめします。

  1. 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 とな

  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」のように数列で連続する数字が、グリッド上で上下左右・斜めに隣り合わないように配置