J'ai créé une demande pour une telle fonctionnalité sur Microsoft Connect. Si c'est quelque chose que vous recherchez, veuillez voter pour cette demande et augmenter sa visibilité.
https://connect.microsoft.com/VisualStudio/feedback/details/634346/guassian-normal-distribution-random-numbers
Cette fonctionnalité est incluse dans le SDK Java. Son implémentation est disponible [dans le cadre de la documentation](http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#nextGaussian()) et est facilement portable vers C# ou d'autres langages .NET.
Si vous recherchez la vitesse pure, alors le Algorithme de Zigorat est généralement reconnue comme l'approche la plus rapide.
Je ne suis pas un expert en la matière, mais j'en ai eu besoin lors de la mise en œuvre d'un système de gestion de l'information. filtre à particules pour mon Bibliothèque de football robotisé simulé RoboCup 3D et j'ai été surpris que cela ne soit pas inclus dans le cadre.
En attendant, voici un wrapper pour Random
qui fournit une mise en œuvre efficace de la méthode polaire de Box Muller :
public sealed class GaussianRandom
{
private bool _hasDeviate;
private double _storedDeviate;
private readonly Random _random;
public GaussianRandom(Random random = null)
{
_random = random ?? new Random();
}
/// <summary>
/// Obtains normally (Gaussian) distributed 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 NextGaussian(double mu = 0, double sigma = 1)
{
if (sigma <= 0)
throw new ArgumentOutOfRangeException("sigma", "Must be greater than zero.");
if (_hasDeviate)
{
_hasDeviate = false;
return _storedDeviate*sigma + mu;
}
double v1, v2, rSquared;
do
{
// two random values between -1.0 and 1.0
v1 = 2*_random.NextDouble() - 1;
v2 = 2*_random.NextDouble() - 1;
rSquared = v1*v1 + v2*v2;
// ensure within the unit circle
} while (rSquared >= 1 || rSquared == 0);
// calculate polar tranformation for each deviate
var polar = Math.Sqrt(-2*Math.Log(rSquared)/rSquared);
// store first deviate
_storedDeviate = v2*polar;
_hasDeviate = true;
// return second deviate
return v1*polar*sigma + mu;
}
}
0 votes
http://mathworld.wolfram.com/Box-MullerTransformation.html En utilisant deux variables aléatoires, vous pouvez générer des valeurs aléatoires selon une distribution gaussienne. Ce n'est pas du tout une tâche difficile.
1 votes
Je voudrais juste ajouter un résultat mathématique qui n'est pas immédiatement utile pour les distributions normales (en raison de la CDF complexe), mais qui est utile pour de nombreuses autres distributions. Si vous placez des nombres aléatoires uniformément distribués dans [0,1] (avec
Random.NextDouble()
) dans l'inverse de la CDF de N'IMPORTE QUELLE distribution, vous obtiendrez des nombres aléatoires qui suivent CETTE distribution. Si votre application n'a pas besoin de variables précisément distribuées normalement, alors la distribution logistique est une approximation très proche de la normale et possède une CDF facilement inversible.1 votes
Le site Paquet NuGet MedallionRandom contient une méthode d'extension permettant de récupérer les valeurs normalement distribuées d'une
Random
en utilisant la transformation de Box-Muller (mentionnée dans plusieurs réponses ci-dessous).