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

C/C++で正規分布に従う乱数を生成する方法

本記事では、正規分布(ガウス分布)に従う乱数をC/C++で生成する方法を解説します。正規乱数は、Box-Muller法と呼ばれる変換公式を使うことで、一様乱数から簡単に求められます。その公式は次の通りです。

𝑧 = √−2 ln 𝑥1 cos (2𝜋𝑥2)

ここで、x1 と x2 はそれぞれ「0以上1未満」の範囲でランダムに選ばれた一様乱数です。この式によって得られる z は、平均0・標準偏差1の標準正規分布に従います。

サンプルコード

以下は、この公式を実装したC++のプログラム例です。生成した標準正規乱数に標準偏差(sigma)を掛け、平均値(Mi)を加算することで、任意の平均・分散を持つ正規乱数を作っています。

#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
using namespace std;

// 0以上1未満の一様乱数を返す
double rand_gen() {
    return ((double)(rand()) + 1.) / ((double)(RAND_MAX) + 1.);
}

// 正規分布に従う乱数を返す(Box-Muller法)
double normalRandom() {
    double v1 = rand_gen();
    double v2 = rand_gen();
    return cos(2 * 3.14 * v2) * sqrt(-2. * log(v1));
}

int main() {
    double sigma = 82.0; // 標準偏差
    double Mi = 40.0;    // 平均値
    for (int i = 0; i < 20; i++) {
        double x = normalRandom() * sigma + Mi;
        cout << " x = " << x << endl;
    }
}

実行結果

x = 1.91628
x = 57.0448
x = 51.4348
x = 53.5612
x = -83.8511
x = -28.9197
x = -76.0576
x = 62.1435
x = 23.9
x = -87.0663
x = 50.6942
x = 94.1685
x = -88.1597
x = 168.502
x = 40.7563
x = 90.1091
x = 16.9218
x = -36.9178
x = 135.969
x = 56.8888

コードのポイント

rand_gen()関数:rand()が返すのは0〜RAND_MAXの整数値のため、これをRAND_MAX+1で割ることで0以上1未満の実数に変換しています。分子に1を加えているのは、v1が0になるとlog(0)が計算できなくなる(マイナス無限大になる)ことを防ぐためです。

normalRandom()関数:2つの一様乱数v1、v2を用いてBox-Muller変換を行い、標準正規分布に従う値を返します。

sigma と Mi:標準正規乱数に対して「×標準偏差 + 平均値」という線形変換を施すことで、平均Mi・標準偏差sigmaの正規分布に従う乱数へと調整できます。

補足:より実用的な使い方

上記のコードではsrand()を呼び出していないため、毎回同じ乱数列が生成されます。実行ごとに異なる結果が必要な場合は、main関数の先頭で srand(time(NULL)); を呼び出してください。

また、C++11以降では <random> ヘッダーの std::normal_distribution を使えば、より高品質な正規乱数を簡単に生成できます。自前実装は学習目的やレガシー環境向けと考え、実務では標準ライブラリの活用を推奨します。

  1. Pythonで疑似乱数を生成する方法|randomモジュールの使い方を徹底解説

    多くのコンピュータアプリケーションでは、乱数の生成が必要になります。しかし、コンピュータが生成できるのは「真の乱数」ではなく、あくまで規則性に基づいた疑似乱数です。 Pythonも他のプログラミング言語と同様に疑似乱数ジェネレーターを使用しており、その基盤となっているのは「メルセンヌ・ツイスタ(Mersenne Twister)」というアルゴリズムです。このアルゴリズムは53ビット精度の浮動小数点数を生成し、高速かつスレッドセーフであることが特徴ですが、暗号化用途には適していません。 Pythonの標準ライブラリには random モジュールが含まれており、乱数を扱うためのさまざまな関数が定義

  2. PythonのNumPyで乱数を生成する方法を徹底解説

    NumPyパッケージには、乱数の生成に役立つさまざまな関数が含まれた random モジュール が用意されています。この記事では、特に利用頻度の高い rand()、randn()、randint()、random() の4つの関数について、実際のコード例とともにわかりやすく解説します。 numpy.random.rand():一様分布の乱数配列を作成する numpy.random.rand() は、指定した形状(シェイプ)の配列を作成し、その要素を「0以上1未満」の一様分布から抽出されたランダムなサンプルで満たします。引数に配列の次元サイズを渡します。 >>> import