C++中的Marsaglia正态随机变量

Marsaglia Normal Random Variables in C++

本文关键字:随机 变量 中的 Marsaglia C++      更新时间:2023-10-16

我的查询非常简单。我更喜欢用Java编写数值方法,但经常需要用C++做一些事情。我喜欢Java中的高斯随机变量,因为它使用Marsaglia算法并保持两个Normal随机变量。它在第一次调用时返回一个,在第二次调用中返回第二个,并且直到第三次调用才再次进行昂贵的计算。使用下面的oracle链接(在程序注释中),我试图用C++实现这段代码,但不知道如何编写C++版本的"同步"公共方法,这将允许我使用两个Normal随机变量。我不是一个专业的程序员,所以任何指导都将不胜感激。

简而言之,我想保留:

v2*乘数

// This function is Similar to the GNU 
// Java Implementation as seen on
// http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#nextGaussian%28%29
double nextGaussian() {
    double v1, v2, s, nextNextGaussian;
    do { 
        v1 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
        v2 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
        s = v1 * v1 + v2 * v2;
    } while (s >= 1 || s == 0);
    double multiplier = sqrt(-2 * log(s)/s);
    nextNextGaussian = v2 * multiplier;
    return v1 * multiplier;
}

只需将nextGaussianVal声明为静态,即

static double nextGaussianVal;

然后,nextGaussianVal的值将在下次调用该方法时可用。您可能还需要另一个静态变量来跟上当前计数,如下所示:

double nextGaussian()
{
    static int count = 0;
    static double nextGaussianVal;
    double firstGaussianVal, v1, v2, s;
    if (count == 0) {
       do { 
           v1 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
           v2 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
           s = v1 * v1 + v2 * v2;
        } while (s >= 1 || s == 0);
        double multiplier = sqrt(-2 * log(s)/s);
        nextGaussianVal = v2 * multiplier;
        firstGaussianVal = v1 * multiplier;
        count = 1;
        return firstGaussianVal;
    }
    count = 0;
    return nextGaussianVal;
}

编辑:更详细的解释——第一次调用函数时,count被初始化为零。根据if语句,执行有问题的计算,并假设firstGaussianValnextGaussianVal被赋值,count被赋值为1,并返回firstGaussian Valount将具有其先前分配的值1,并且nextGaussianVal包含其在第一次调用期间先前分配的数值——也就是说,由于count现在是1,因此函数将基于if语句,将零分配给计数并返回nextGaussianVal。冲洗,重复。。。

在更面向对象的情况下,您应该将这些东西保存在"随机数生成器"对象中。例如,查看以下代码:https://code.cor-lab.org/projects/nemomath/repository/entry/trunk/nemomath/src/nemo/Random.h类"gaussian"以算法的方式实现了你想要的东西。

以上建议的问题是COUNT变量应该是BOOLEAN,而不是整数。此外,存储的高斯也需要是静态的。

我要感谢大家的帮助,帮助我找到我想要的正确解决方案。我知道这个片段属于一个对象。我现在有理由把它放在一个文件里。

double nextGaussian() {
    // Static variables allow the function to make use of
    // both Gaussian Random variables.  Generated by the polar Marsaglia 
    // method This makes the function much more efficient with will 
    // pay off for simulations
    static bool hasNextGaussian = false;
    static double nextNextGaussian;
    double v1, v2, s;
    if (!hasNextGaussian) {
        do {
            v1 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
            v2 = 2 * nextUniform() - 1;   // between -1.0 and 1.0
            s = v1 * v1 + v2 * v2;
        } while (s >= 1 || s == 0);
        double multiplier = sqrt(-2 * log(s)/s);
        nextNextGaussian = v2 * multiplier;
        hasNextGaussian = true;
        return v1 * multiplier;
    } else {
        hasNextGaussian = false;
        return nextNextGaussian;
    }
}

double nextUniform(){

double Uniform = rand() / double(RAND_MAX);
return Uniform;

}