3

0 と 1 の間 (0 を含み、1 を除く) に正規分布するランダムに生成された値を保持するのに問題があります。アルゴリズムは基本的に正しいと思いますが、ここで困惑しています。どんな洞察も素晴らしいでしょう。

必要なインクルード ファイルは次のとおりです。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

正規分布乱数ジェネレータ関数:

float rand_normal(float mean, float stddev) 
{
    static float n2 = 0.0;
    float x, y, r;
    static int n2_cached = 0;
    if (!n2_cached) 
    {
        do
        {
            x = 2.0*rand()/RAND_MAX - 1;
            y = 2.0*rand()/RAND_MAX - 1;
            r = x*x + y*y;
        } while (r==0.0 || r>1.0);
        float d = sqrt(-2.0*log(r)/r);
        float n1 = x*d;
        float result = n1*stddev + mean;
        n2 = y*d;
        n2_cached = 1;
        return result;
    }
    else
    {
        n2_cached = 0;
        return n2*stddev + mean;
    }
}

メイン関数はテスト目的でのみ使用されます。

int main()
{
    srand(time(NULL));
    int i;
    float min = 0.5, max = 0.5, r, avg = 0;
    float x, w;
    int n = 10000000;
    for (i=0; i<n; i++)
    {
        r = rand_normal(0.5, 0.09);
        if (r < min)
            min = r;
        else if ( r>max)
            max = r;
        avg += r;
    }
    avg /= (float)n;
    printf("min = %f\nmax = %f\navg = %f\n", min, max, avg);
    return 0;
}    

念のために言っておきますが、この関数は「植物の遺伝的継承」のシミュレーションに必要です。

4

2 に答える 2

3

結果が 0 から 1 の間に留まることを期待するのはなぜですか? ガウス分布は完全にサポートされているため、どのような間隔を調べ、どのような平均と分散を選択しても、その間隔の外に出る (可能性は非常に小さい) ゼロではない確率が常に存在します。なんらかの理由で本当に [0,1] に制限したい場合は、その間隔に入るまで rand_normal を呼び出すだけです。

Box-Müller (使用しているアルゴリズム) は簡単に実装できますが、これはガウス確率変数を生成する最悪で最もコストのかかる方法の 1 つです。私が知っている最高かつ最速のアルゴリズムは「ジッグラト」メソッドであり、その実装は次の場所にあります。

http://www.seehuhn.de/pages/ziggurat

于 2012-06-27T13:45:19.323 に答える
0

「rand()」を正規化された浮動小数点値に変換する関数を必ず作成します。例えば:

double
nrand ()
{
  return rand()/(RAND_MAX - 1);
}

また、役立つリンクがいくつかあります。

于 2012-01-19T18:19:29.307 に答える