문제

.NET 표준 라이브러리에 가우시안 분포를 따르는 임의 변수를 만들 수있는 기능을 제공하는 클래스가 있습니까?

도움이 되었습니까?

해결책

Box-Muller Transform 사용에 대한 Jarrett의 제안은 빠른 솔루션에 좋습니다. 간단한 구현 :

Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
             Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
             mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)

다른 팁

이 질문은 .NET Gaussian Generation을 위해 Google 위에서 옮긴 것으로 보이므로 답을 게시 할 것이라고 생각했습니다.

나는 일부를 만들었다 .NET 랜덤 클래스의 확장 방법, Box-Muller Transform의 구현을 포함하여. 프로젝트가 포함되어있는 한 (또는 컴파일 된 DLL을 참조) 확장자이므로 여전히 할 수 있습니다.

var r = new Random();
var x = r.NextGaussian();

뻔뻔한 플러그를 아무도 신경 쓰지 않기를 바랍니다.

결과의 샘플 히스토그램 (그림을 그리기위한 데모 앱) : 포함) :

enter image description here

Math.net 이 기능을 제공합니다. 방법은 다음과 같습니다.

double mean = 100;
double stdDev = 10;

MathNet.Numerics.Distributions.Normal normalDist = new Normal(mean, stdDev);
double randomGaussianValue=   normalDist.Sample();

여기에서 문서를 찾을 수 있습니다.http://numerics.mathdotnet.com/api/mathnet.numerics.distributions/normal.htm

Microsoft Connect에서 그러한 기능에 대한 요청을 만들었습니다. 이것이 당신이 찾고있는 것이라면, 투표하고 가시성을 높이십시오.

https://connect.microsoft.com/visualstudio/feedback/details/634346/guassian-normal-distribution-random-numbers

이 기능은 Java SDK에 포함되어 있습니다. 구현을 사용할 수 있습니다 문서의 일부로 C# 또는 기타 .NET 언어로 쉽게 포팅됩니다.

순수한 속도를 찾고 있다면 Zigorat 알고리즘 일반적으로 가장 빠른 접근법으로 인식됩니다.

나는이 주제에 대한 전문가가 아닙니다. 입자 필터 나를 위해 RoboCup 3D 시뮬레이션 로봇 축구 도서관 이것이 프레임 워크에 포함되지 않았을 때 놀랐습니다.


한편, 여기에 래퍼가 있습니다 Random Box Muller Polar Method의 효율적인 구현을 제공합니다.

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;
    }
}

Math.net Iridium 또한 "비 균일 랜덤 생성기 (정상, 포아송, 이항, ...)를 구현한다고 주장합니다.

다음은 임의 변수를 생성하기위한 또 다른 빠르고 더러운 솔루션입니다. 정상 분포. 임의의 포인트 (x, y)를 그립니다.이 점이 확률 밀도 함수의 곡선 아래에 있는지 확인합니다. 그렇지 않으면 반복합니다.

보너스 : 다른 분포에 대한 임의 변수를 생성 할 수 있습니다 (예 : 지수 분포 또는 포아송 분포) 밀도 기능을 대체하여.

    static Random _rand = new Random();

    public static double Draw()
    {
        while (true)
        {
            // Get random values from interval [0,1]
            var x = _rand.NextDouble(); 
            var y = _rand.NextDouble(); 

            // Is the point (x,y) under the curve of the density function?
            if (y < f(x)) 
                return x;
        }
    }

    // Normal (or gauss) distribution function
    public static double f(double x, double μ = 0.5, double σ = 0.5)
    {
        return 1d / Math.Sqrt(2 * σ * σ * Math.PI) * Math.Exp(-((x - μ) * (x - μ)) / (2 * σ * σ));
    }

중요 : 간격을 선택하십시오 와이 그리고 매개 변수 σ 그리고 μ 함수의 곡선이 최대/최소 점 (예 : x = 평균)에서 컷오프하지 않도록합니다. 간격을 생각하십시오 엑스 그리고 와이 곡선이 맞아야하는 경계 상자로.

@yoyoyoyosef의 대답을 더 빨리 만들고 래퍼 클래스를 작성하여 확장하고 싶습니다. 발생한 오버 헤드는 두 배나 빠른 의미는 없지만 거의 두 배 빠른. 그래도 스레드 안전이 아닙니다.

public class Gaussian
{
     private bool _available;
     private double _nextGauss;
     private Random _rng;

     public Gaussian()
     {
         _rng = new Random();
     }

     public double RandomGauss()
     {
        if (_available)
        {
            _available = false;
            return _nextGauss;
        }

        double u1 = _rng.NextDouble();
        double u2 = _rng.NextDouble();
        double temp1 = Math.Sqrt(-2.0*Math.Log(u1));
        double temp2 = 2.0*Math.PI*u2;

        _nextGauss = temp1 * Math.Sin(temp2);
        _available = true;
        return temp1*Math.Cos(temp2);
     }

    public double RandomGauss(double mu, double sigma)
    {
        return mu + sigma*RandomGauss();
    }

    public double RandomGauss(double sigma)
    {
        return sigma*RandomGauss();
    }
}

Drew Noakes의 답변을 확장하면 Box-Muller (약 50-75% 더 빠른)보다 더 나은 성능이 필요한 경우 Colin Green은 C#에서 Ziggurat 알고리즘의 구현을 공유했습니다.

http://heliospan.org/zigguratalgorithm/zigguratalgorithm.html

Ziggurat는 조회 테이블을 사용하여 곡선에서 충분히 떨어지는 값을 처리하여 빠르게 수락하거나 거부합니다. 시간의 약 2.5%는 숫자의 곡선의 어느 쪽이 켜져 있는지 확인하기 위해 추가 계산을 수행해야합니다.

@Noakes와 @Hameer의 답변을 확장하여 'Gaussian'클래스를 구현했지만 메모리 공간을 단순화하기 위해 Random Class의 자녀가되어 기본 Next (), NextDouble ()를 호출 할 수 있도록했습니다. 가우시안 클래스의 등을 처리하여 추가 임의의 객체를 만들 필요없이. 또한이 클래스가 인스턴스 기반이기 때문에 필요한 것으로 보지 않았기 때문에 _available 및 _nextgauss Global Class 속성을 제거했습니다. 각 스레드에 고유 한 가우시안 객체를 제공하면 스레드 안전이어야합니다. 또한 모든 런타임 할당 된 변수를 함수에서 옮기고 클래스 속성을 만들었습니다. 이는 객체가 파괴 될 때까지 이론적으로 비 할당되지 않아야하기 때문에 메모리 관리자에 대한 호출 수를 줄입니다.

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));
    }
}

당신은 ult.net을 시도 할 수 있습니다. 그래도 상업용 라이센스는 아닙니다. 여기 있습니다 링크

.NET가 Microsoft Research를 개발하기위한 확률 론적 프레임 워크입니다. 여기에는 Bernoulli, Beta, Gamma, Gaussian, Poisson의 분포에 대한 .NET 유형이 있으며 아마도 내가 빠질 것입니다.

그것은 당신이 원하는 것을 성취 할 수 있습니다. 감사.

이것은 나의 간단한 박스 뮬러 영감 구현입니다. 당신은 당신의 요구에 맞게 분해능을 늘릴 수 있습니다. 이것은 나에게 훌륭하게 작동하지만, 이것은 제한된 범위 근사치이므로 꼬리가 닫히고 유한하다는 것을 명심하십시오. 그러나 확실히 필요에 따라 확장 할 수 있습니다.

    //
    // by Dan
    // islandTraderFX
    // copyright 2015
    // Siesta Key, FL
    //    
// 0.0  3231 ********************************
// 0.1  1981 *******************
// 0.2  1411 **************
// 0.3  1048 **********
// 0.4  810 ********
// 0.5  573 *****
// 0.6  464 ****
// 0.7  262 **
// 0.8  161 *
// 0.9  59 
//Total: 10000

double g()
{
   double res = 1000000;
   return random.Next(0, (int)(res * random.NextDouble()) + 1) / res;
}

public static class RandomProvider
{
   public static int seed = Environment.TickCount;

   private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
       new Random(Interlocked.Increment(ref seed))
   );

   public static Random GetThreadRandom()
   {
       return randomWrapper.Value;
   }
} 

나는 생각하지 않습니다. 그리고 프레임 워크가 이미 충분히 부풀어 오르기 때문에, 그러한 특수 기능이 더 많이 채워지지 않기 때문에 나는 정말로 희망합니다.

보세요 http://www.extremeoptimization.com/statistics/usersguide/continuousdistributions/normaldiption.aspx 그리고 http://www.vbforums.com/showthread.php?t=488959 그러나 제 3 자 .NET 솔루션의 경우.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top