La mise en œuvre de Fort-Mueller générateur de nombres aléatoires en C#

De cette question: générateur de nombre Aléatoire qui gravite chiffres à un nombre donné dans la gamme? j'ai fait quelques recherches depuis que je suis arrivé sur un générateur de nombre aléatoire avant. Je me souviens, a été le nom "Müller", donc je suppose que je l'ai trouvé, ici:

Je peut trouver de nombreuses applications dans d'autres langues, mais je n'arrive pas à le mettre en œuvre correctement en C#.

Cette page, par exemple, La Méthode de Box-Muller pour la Génération de Nombres Aléatoires Gaussiennes dit que le code devrait ressembler à ceci (ce n'est pas 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;
}

Maintenant, voici ma mise en œuvre de la ci-dessus en C#. Notez que le transformer en produit de 2 nombres, d'où l'astuce de la "phase" ci-dessus. J'ai simplement jeter la deuxième valeur, et de retour de la première.

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

Ma question est la suivante scénario spécifique, où mon code ne retourne pas une valeur dans la plage de 0 à 1, et je ne peux pas comprendre comment le code original peut.

  • u = 0.5, v = 0.1
  • S devient 0.5*0.5 + 0.1*0.1 = 0.26
  • fac devient ~3.22
  • la valeur de retour est donc ~0.5 * 3.22 ou ~1.6

Qui n'est pas dans 0 .. 1.

Ce que je fais mal/ne pas comprendre?

Si j'ai modifier mon code pour que, au lieu de multiplier les fac avec u, je multiplie par S, j'obtiens une valeur qui varie de 0 à 1, mais il a la mauvaise distribution (semble avoir une répartition maximale autour de 0,7-0,8 et puis ralentit dans les deux directions.)

Notez que j'ai vérifié quelques exemples de code ci-dessus, généralement en C ou en Java, et ils se ressemblent tous à peu près la même.
Êtes-vous sûr que le code C génère exactement ce que vous voulez?

OriginalL'auteur Lasse Vågsæther Karlsen | 2011-04-28