Marsaglia在C++中的随机变量
我的查询非常简单。我更喜欢用Java编写数值方法,但通常需要在C++中做一些事情。我喜欢Java中的高斯随机变量,因为它使用Marsaglia算法并保留了两个Normal随机变量。它在第一次通话中返回一个,在第二次通话中返回第二个,并且在第三次通话之前不再进行昂贵的计算。使用下面的oracle链接(在程序注释中)我尝试在C++中实现这个代码,但不知道如何编写“Synchronized”公共方法的C++版本,这将允许我使用两个Normal随机变量。我不是一个专业的程序员,所以任何指导将不胜感激。Marsaglia在C++中的随机变量
总之我想保留:
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的价值将可用的nex该方法被调用。您可能还需要另一个静态变量与当前计数跟上,像这样:
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;
}
编辑:更详细的解释 - 在第一次调用函数时,计数被初始化为零。基于该如果声明,相关计算进行扫描,并且假定firstGaussianVal和nextGaussianVal被赋值,计数分配一个值,并firstGaussianVal返回。下一次函数被调用时,计数将具有其先前分配的值1,并且nextGaussianVal将包含它在第一次调用期间先前分配的值 - 也就是说,因为计数现在是一个,该功能将基于if声明,将0分配给计数并返回nextGaussianVal。冲洗,重复...
我不认为这解决了问题,但我可能是错的。我没有看到函数如何知道何时返回未使用的变量以及何时实际运行DO命令。你可以再详细一点吗? – JJJ 2012-02-03 04:56:04
第二次调用在返回IF ELSE树之前将不会被设置回0,这使得ELSE部分无法访问? – JJJ 2012-02-03 05:08:09
不,静态变量声明中的零值只在第一次调用该方法时被赋值,因为它实际上是静态的... – hatboyzero 2012-02-03 05:09:15
在一个更面向对象的问题,你应该保持在一个“随机数发生器”的对象的东西。请在此代码处查找实例: https://code.cor-lab.org/projects/nemomath/repository/entry/trunk/nemomath/src/nemo/Random.h “高斯”类以您想要的算法实现您想要的内容。
上述建议的问题是,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;
}
}
双nextUniform(){
double Uniform = rand()/double(RAND_MAX);
return Uniform;
}
除了使用布尔值而不是计数变量的事实之外,这与以上建议的功能有何不同?我仍然很难理解上面提供的例子*在这个例子中没有工作(假设nextUniform()的定义在两种情况下都是相同的)。 – hatboyzero 2012-02-08 16:38:51
只是好奇,但回答暗指解决代码中的一个更大的问题......这似乎没有完全解释/引用你的问题。这使事情有点混乱。你会介意扩大你的问题来澄清一下这里可能缺少的部分吗?我只想充分看到整个思路。谢谢。 – skyburner 2012-02-08 16:54:52
我认为就我而言,关键在于无论您是使用整数还是布尔值来管理您所处的状态均无关紧要,这两个示例中描述的行为应该是**相同的**。 True与1相同,False与0相同,条件**(!hasNextGaussian)**将返回与**(count == 0)**相同的值。 – hatboyzero 2012-02-08 17:30:48
这不是完全清楚的代码的问题,你有* *是什么。 – 2012-02-03 04:39:56
那么我只返回一个变量a的代码会抛出另一个。当我需要下一个随机变量时,我必须经历再次生成两个均匀随机变量的繁重工作。这次像最后一次,我得到一个正常房车,并把另一个扔掉。在Java中,你返回一个Normal变量并保留下一次调用的第二个变量。所以你做了一半的工作。这对我的使用非常重要,因为我的一些算法需要数天才能运行。 – JJJ 2012-02-03 04:41:26