【发布时间】:2012-11-28 03:38:31
【问题描述】:
来自this question: Random number generator which gravitates numbers to any given number in range? 我做了一些研究,因为我以前遇到过这样的随机数生成器。我只记得“Mueller”这个名字,所以我想我在这里找到了它:
我可以找到许多其他语言的实现,但我似乎无法在 C# 中正确实现。
这个页面,例如,The Box-Muller Method for Generating Gaussian Random Numbers 说代码应该是这样的(这不是 C#):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
double gaussian(void)
{
static double v, fac;
static int phase = 0;
double S, Z, U1, U2, u;
if (phase)
Z = v * fac;
else
{
do
{
U1 = (double)rand() / RAND_MAX;
U2 = (double)rand() / RAND_MAX;
u = 2. * U1 - 1.;
v = 2. * U2 - 1.;
S = u * u + v * v;
} while (S >= 1);
fac = sqrt (-2. * log(S) / S);
Z = u * fac;
}
phase = 1 - phase;
return Z;
}
现在,这是我在 C# 中对上述内容的实现。请注意,转换会产生 2 个数字,因此使用上面的“相位”的技巧。我只是丢弃第二个值并返回第一个值。
public static double NextGaussianDouble(this Random r)
{
double u, v, S;
do
{
u = 2.0 * r.NextDouble() - 1.0;
v = 2.0 * r.NextDouble() - 1.0;
S = u * u + v * v;
}
while (S >= 1.0);
double fac = Math.Sqrt(-2.0 * Math.Log(S) / S);
return u * fac;
}
我的问题是针对以下特定场景,我的代码没有返回 0-1 范围内的值,我也无法理解原始代码是如何返回的。
- u = 0.5,v = 0.1
- S 变为
0.5*0.5 + 0.1*0.1=0.26 - fac 变为 ~
3.22 - 因此返回值为 ~
0.5 * 3.22或 ~1.6
这不在0 .. 1 范围内。
我做错了什么/不理解?
如果我修改我的代码,而不是将fac 与u 相乘,而是乘以S,我得到一个介于0 到1 之间的值,但它的分布错误(似乎有一个最大分布在 0.7-0.8 左右,然后在两个方向逐渐减小。)
【问题讨论】:
-
请注意,我检查了上述代码的几个示例,通常使用 C 或 Java,它们看起来都差不多。
-
您确定 C 代码生成的正是您想要的吗?
标签: c# random non-uniform-distribution