Umsetzung der Box-Müller-random number generator in C#

Vom diese Frage: Random number generator, die gravitiert zahlen, um beliebig viele in Reihe? habe ich einige der Forschung, da habe ich über eine solche Zufallszahl-generator vor. Alle, die ich mich erinnere, war der name "Müller", also denke ich, ich habe es gefunden, hier:

Finde ich zahlreiche Implementierungen in anderen Sprachen, aber ich kann nicht scheinen, um es zu implementieren korrekt in C#.

Dieser Seite, zum Beispiel, Die Box-Muller-Methode zur Erzeugung Gauß-Zufallszahlen sagt, der code sollte wie folgt Aussehen (dies ist nicht C#):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

double gaussian(void)
{
   static double v, fac;
   static int phase = 0;
   double S, Z, U1, U2, u;

   if (phase)
      Z = v * fac;
   else
   {
      do
      {
         U1 = (double)rand() / RAND_MAX;
         U2 = (double)rand() / RAND_MAX;

         u = 2. * U1 - 1.;
         v = 2. * U2 - 1.;
         S = u * u + v * v;
      } while (S >= 1);

      fac = sqrt (-2. * log(S) / S);
      Z = u * fac;
   }

   phase = 1 - phase;

   return Z;
}

Nun, hier ist meine Umsetzung der oben in C#. Beachten Sie, dass die Transformation ergibt 2 zahlen, daher der trick mit der "phase" über. Ich habe einfach entsorgen Sie den zweiten Wert ein und geben Sie die ersten.

public static double NextGaussianDouble(this Random r)
{
    double u, v, S;

    do
    {
        u = 2.0 * r.NextDouble() - 1.0;
        v = 2.0 * r.NextDouble() - 1.0;
        S = u * u + v * v;
    }
    while (S >= 1.0);

    double fac = Math.Sqrt(-2.0 * Math.Log(S) / S);
    return u * fac;
}

Meine Frage ist, mit den folgenden spezifischen Szenario, wo mein code nicht wieder ein Wert im Bereich von 0-1, und ich kann nicht verstehen, wie der ursprüngliche code kann entweder.

  • u = 0.5, v = 0.1
  • S wird 0.5*0.5 + 0.1*0.1 = 0.26
  • fac wird ~3.22
  • der return-Wert ist somit ~0.5 * 3.22 oder ~1.6

Nicht innerhalb 0 .. 1.

Was mache ich falsch/nicht zu verstehen?

Wenn ich ändern mein code so, dass anstelle der Multiplikation fac mit u ich mal S bekomme ich einen Wert im Bereich von 0 bis 1, aber es hat die falsche distribution (scheint eine maximale Verteilung rund 0,7-0,8 und dann verjüngt sich in beide Richtungen.)

  • Beachten Sie, dass ich habe ein paar Beispiele von den oben genannten code, in der Regel in C oder Java, und Sie sehen alle so ziemlich das gleiche.
  • Sind Sie sicher, dass der C-code erzeugt genau das, was Sie wollen?
Schreibe einen Kommentar