Расширяя ответы @Noakes и @ Hameer, я также реализовал класс 'Gaussian', но чтобы упростить пространство памяти, я сделал его дочерним по отношению к классу Random, чтобы вы также могли вызывать базовый Next (), NextDouble () и т.д. из гауссовского класса, а также без необходимости создания дополнительного объекта Random для его обработки. Я также исключил свойства глобального класса _available и _nextgauss, поскольку не считал их необходимыми, поскольку этот класс основан на экземплярах, поэтому он должен быть потокобезопасным, если вы предоставляете каждому потоку свой гауссов объект. Я также переместил все переменные, выделенные во время выполнения, из функции и сделал их свойствами класса, это уменьшит количество обращений к диспетчеру памяти, поскольку теоретически 4 двойных числа никогда не должны перераспределяться, пока объект не будет уничтожен.
public class Gaussian : Random
{
private double u1;
private double u2;
private double temp1;
private double temp2;
public Gaussian(int seed):base(seed)
{
}
public Gaussian() : base()
{
}
/// <summary>
/// Obtains normally (Gaussian) distrubuted random numbers, using the Box-Muller
/// transformation. This transformation takes two uniformly distributed deviates
/// within the unit circle, and transforms them into two independently distributed normal deviates.
/// </summary>
/// <param name="mu">The mean of the distribution. Default is zero</param>
/// <param name="sigma">The standard deviation of the distribution. Default is one.</param>
/// <returns></returns>
public double RandomGauss(double mu = 0, double sigma = 1)
{
if (sigma <= 0)
throw new ArgumentOutOfRangeException("sigma", "Must be greater than zero.");
u1 = base.NextDouble();
u2 = base.NextDouble();
temp1 = Math.Sqrt(-2 * Math.Log(u1));
temp2 = 2 * Math.PI * u2;
return mu + sigma*(temp1 * Math.Cos(temp2));
}
}