C# 生成高斯范围内的随机数?
我想使用一个随机数生成器,在高斯范围内创建随机数,我可以自己定义中值。我已经在这里问了一个类似的问题,现在我使用以下代码:C# 生成高斯范围内的随机数?,c#,.net,algorithm,random,gaussian,C#,.net,Algorithm,Random,Gaussian,我想使用一个随机数生成器,在高斯范围内创建随机数,我可以自己定义中值。我已经在这里问了一个类似的问题,现在我使用以下代码: class RandomGaussian { private static Random random = new Random(); private static bool haveNextNextGaussian; private static double nextNextGaussian;
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;
}
}
}
类随机变量
{
私有静态随机=新随机();
私有静态bool haveNextNextGaussian;
私有静态双NextNextNextGaussian;
公共静态双高斯范围(双起点、双均值、双终点)
{
if(!(从to)
{
if(retval到)
retval=to-(retval-to);
}
返回返回;
}
私有静态双NextGaussian()
{
if(haveNextNextGaussian)
{
haveNextNextGaussian=false;
返回nextNextGaussian;
}
其他的
{
双v1,v2,s;
做
{
v1=2*random.NextDouble()-1;
v2=2*random.NextDouble()-1;
s=v1*v1+v2*v2;
}而(s>=1 | | s==0);
双乘数=Math.Sqrt(-2*Math.Log)/s;
nextNextGaussian=v2*乘数;
haveNextNextGaussian=true;
返回v1*乘法器;
}
}
}
然后为了验证结果,我用高斯范围(0,0.5,1)绘制了n=100000000的图
正如人们所看到的,中间值实际上是0.5,但实际上没有一条可见的曲线。那我做错了什么
编辑
我想要的是这样的,通过传递一个值,我可以自己设置最高的概率
在特定范围内绘制正常偏差的最简单方法是使用拒绝采样:
do {
retval = NextGaussian() * stdev + mean;
} while (retval < from || to < retval);
截尾分布的CDF为
F(retval) = (1 + erf((retval-mean) / (stdev*sqrt(2)))) / 2
C(retval) = (F(retval) - F(from)) / (F(to) - F(from)), from ≤ x < to
您可以预先计算特定参数的t1
和t2
。这种方法的优点是没有拒绝采样,因此每次绘制只需要一个NextDouble()
。如果[from,to]间隔很小,则速度会更快
但是,听起来您可能希望使用图形生成器。我的图形生成器中有类似的方法(必须对其进行一些修改): 使用具有特定范围的生成器函数返回随机浮点数:
private double NextFunctional(Func<double, double> func, double from, double to, double height, out double x)
{
double halfWidth = (to - from) / 2;
double distance = halfWidth + from;
x = this.rand.NextDouble() * 2 - 1;// -1 .. 1
double y = func(x);
x = halfWidth * x + distance;
y *= height;
return y;
}
使用随机数生成图形的方法:
private void PlotGraph(Graphics g, Pen p, double from, double to, double height)
{
for (int i = 0; i < 1000; i++)
{
double x;
double y = this.NextFunctional(this.Gauss, from, to, height, out x);
this.DrawPoint(g, p, x, y);
}
}
NextFunctional()
方法中的out double x
参数就在那里,因此您可以在图形上轻松地测试它(我的方法中使用了迭代器)。您说的是中间值,但代码说的是平均值。你说的是高斯分布(它可以取任何实数),但你要限制在一个有限的范围内。我想在我能够帮助编写代码之前,我需要知道规范是什么。@David Heffernan yes抱歉意思是正确的。这是最初的问题:高斯函数有无限的支持,你不能在给定的范围内生成它…这看起来不错,但当用高斯函数范围(0,500,1000)测试它时,我只得到494到506之间的值。@Roflcoptr–stdev
在你的图中是σ。它不一定与[from;to]范围相关。
private double Gauss(double x)
{
// Graph should look better with double-x scale.
x *= 2;
double σ = 1 / Math.Sqrt(2 * Math.PI);
double variance = Math.Pow(σ, 2);
double exp = -0.5 * Math.Pow(x, 2) / variance;
double y = 1 / Math.Sqrt(2 * Math.PI * variance) * Math.Pow(Math.E, exp);
return y;
}
private void PlotGraph(Graphics g, Pen p, double from, double to, double height)
{
for (int i = 0; i < 1000; i++)
{
double x;
double y = this.NextFunctional(this.Gauss, from, to, height, out x);
this.DrawPoint(g, p, x, y);
}
}
double x;
double y = this.NextFunctional(a => Math.Cos(a * Math.PI), from, to, height, out x);