问题描述
我想使用在一个高斯范围内,我可以通过自己定义的中间产生随机数的随机数发生器。我已经问过类似的问题在这里,现在我用这个code:
I want to use a random number generator that creates random numbers in a gaussian range where I can define the median by myself. I already asked a similar question here and now I'm using this code:
class RandomGaussian
{
private static Random random = new Random();
private static bool haveNextNextGaussian;
private static double nextNextGaussian;
public static double gaussianInRange(double from, double mean, double to)
{
if (!(from < mean && mean < to))
throw new ArgumentOutOfRangeException();
int p = Convert.ToInt32(random.NextDouble() * 100);
double retval;
if (p < (mean * Math.Abs(from - to)))
{
double interval1 = (NextGaussian() * (mean - from));
retval = from + (float)(interval1);
}
else
{
double interval2 = (NextGaussian() * (to - mean));
retval = mean + (float)(interval2);
}
while (retval < from || retval > to)
{
if (retval < from)
retval = (from - retval) + from;
if (retval > to)
retval = to - (retval - to);
}
return retval;
}
private static double NextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
else
{
double v1, v2, s;
do
{
v1 = 2 * random.NextDouble() - 1;
v2 = 2 * random.NextDouble() - 1;
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = Math.Sqrt(-2 * Math.Log(s) / s);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
}
}
然后以验证结果予绘制它们与gaussianInRange(0,0.5%,1)对于n =亿
Then to verify the results I plotted them with gaussianInRange(0, 0.5, 1) for n=100000000
正如人们所看到的中位数是真正的0.5,但没有真正可见的曲线。所以我在做什么错了?
As one can see the median is really at 0.5 but there isn't really a curve visible. So what I'm doing wrong?
我想是这样的,我可以设置的最高概率由我自己通过传递一个值。
What i want is something like this where I can set the highest probability by myself by passing a value.
推荐答案
绘制偏离正常条件上他们在一个特定的范围是最简单的方法是拒绝采样:
The simplest way to draw normal deviates conditional on them being in a particular range is with rejection sampling:
do {
retval = NextGaussian() * stdev + mean;
} while (retval < from || to < retval);
在画坐标的同样的事情时( V1 的 V2 的)在你无条件的正常生成一个圆圈。
The same sort of thing is used when you draw coordinates (v1, v2) in a circle in your unconditional normal generator.
在值只需折叠的范围之外不产生相同的分布。
Simply folding in values outside the range doesn't produce the same distribution.
另外,如果你有一个很好的实现误差函数和它的逆,可以计算直接使用的数值逆 CDF 。正态分布的CDF是
Also, if you have a good implementation of the error function and its inverse, you can calculate the values directly using an inverse CDF. The CDF of a normal distribution is
F(retval) = (1 + erf((retval-mean) / (stdev*sqrt(2)))) / 2
一个审查分布的CDF为
The CDF of a censored distribution is
C(retval) = (F(retval) - F(from)) / (F(to) - F(from)), from ≤ x < to
要绘制使用CDF随机数,你画 v
从均匀分布[0,1],解决 C(RETVAL) = V
。这给了
To draw a random number using a CDF, you draw v
from a uniform distribution on [0, 1] and solve C(retval) = v
. This gives
double v = random.NextDouble();
double t1 = erf((from - mean) / (stdev*sqrt(2)));
t2 = erf((to - mean) / (stdev*sqrt(2)));
double retval = mean + stdev * sqrt(2) * erf_inv(t1*(1-v) + t2*v);
您可以precalculate T1
和 T2
的具体参数。这种方法的优点是没有排斥反应取样,所以你只需要一个 NextDouble()
每平局。如果[从,到]间隔小,这将是更快的。
You can precalculate t1
and t2
for specific parameters. The advantage of this approach is that there is no rejection sampling, so you only need a single NextDouble()
per draw. If the [from, to] interval is small this will be faster.
不过,这听起来像你可能希望二项分布代替。
However, it sounds like you might want the binomial distribution instead.
这篇关于产生高斯范围内的随机数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!