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?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dein code ist in Ordnung. Dein Fehler ist zu denken, dass sollte es wieder Werte, die ausschließlich im
[0, 1]
. Die (standard -) Normalverteilung ist eine Verteilung mit einem Wert ungleich null Gewicht auf die gesamte Reale Zeile. Das heißt, Werte außerhalb der[0, 1]
sind möglich. In der Tat, die Werte innerhalb[-1, 0]
sind nur als wahrscheinlich, da die Werte innerhalb[0, 1]
, und darüber hinaus der Ergänzung von[0, 1]
hat etwa 66% des Gewichts der normalen Verteilung. Also, 66% der Zeit erwarten wir einen Wert außerhalb[0, 1]
.Auch, ich denke, dies ist nicht die Box-Mueller-Transformation, aber eigentlich ist die polar-Marsaglia-Methode.
Ich bin kein Mathematiker oder Statistiker, aber wenn ich denke, über diese würde ich nicht erwarten, dass eine GAUSS-Verteilung zurück zahlen genau in eine Reihe. Da Ihre Umsetzung den Mittelwert 0 und die Standardabweichung 1, so würde ich erwarten, dass Werte verteilt auf die bell-Kurve mit 0 in der Mitte und dann reduzieren, wie die zahlen weichen von 0 auf beiden Seiten. Also die Reihenfolge wäre auf jeden Fall für die +/- zahlen.
Dann, da es statistische, warum sollte es schwer sein, beschränkt sich auf -1..1, nur weil die std.dev ist 1? Es kann statistisch sein, einige spielen auf beiden Seiten und noch immer erfüllen die statistische Voraussetzung.
Uniform random variate ist in der Tat innerhalb von 0..1, aber der gaussian random variate (was die Box-Muller-Algorithmus erzeugt) können überall auf der reellen Achse. Sehen wiki/NormalDistribution für details.
Ich denke, die Funktion gibt die polar-Koordinaten. So müssen Sie beide Werte um richtige Ergebnisse zu erzielen.
Auch Gauß-Verteilung ist nicht zwischen
0 .. 1
. Es kann leicht am Ende als 1000, aber die Wahrscheinlichkeit eines solchen Auftretens ist sehr gering.Dies ist ein monte-carlo-Methode, so dass Sie nicht Klemmen Sie das Ergebnis, aber was Sie tun können, ist zu ignorieren Proben.