/**
* Generiert standard verteilte PseudozufallsZahlen nach
* Box-Mueller.
*/
public class BoxGenerator
{
/**
* Gibt eine standard verteilte PseudozufallsZahl
* zurück.
*
* @returns double eine standard normal verteilte
* Zufallszahl
*/
public double getGaussDistributedNumber()
{
double result;
if (iHaveSavedARandom())
{
result = getSavedRandom();
}
else
{
RandomPair generatedRandoms = new RandomPair();
setSavedRandom(generatedRandoms.getFirstRandom());
result = generatedRandoms.getSecondRandom();
}
return result;
}
private synchronized void setSavedRandom(double random)
{
savedRandom = random;
iHaveSavedARandom = true;
}
private synchronized double getSavedRandom()
{
iHaveSavedARandom = false;
return savedRandom;
}
private synchronized boolean iHaveSavedARandom()
{
return iHaveSavedARandom;
}
private boolean iHaveSavedARandom = false;
private double savedRandom;
/**
* Kapselung des eigentlichen Algorithmus.
*/
protected static class RandomPair
{
private double firstRandom;
private double secondRandom;
public RandomPair()
{
// Erzeugen eines Punktes im Einheitskreis
double x = getUniformRandom();
double y = getUniformRandom();
while (getSummedProduct(x, y) > 1)
{
x = getUniformRandom();
y = getUniformRandom();
}
// Berechnen des Transformationsfaktors
double transformation;
transformation = Math.log(getSummedProduct(x,y));
transformation *= -2.0;
transformation /= getSummedProduct(x,y);
transformation = Math.sqrt(transformation);
// Ergebnis sichern
firstRandom = x * transformation;
secondRandom = y * transformation;
}
/**
* Erzeugt eine gleichverteilte Zufallszahl im
* Bereich (-1.0,1.0). Hoffentlich. Die Java-
* Dokumentation war hier sehr unzureichend.
*
* @returns double - eine gleichverteilte
* Zufalllszahl
*/
protected double getUniformRandom()
{
return (Math.random() - 0.5) * 2.0;
}
private double getSummedProduct(double x, double y)
{
return (x*x + y*y);
}
/**
* Gibt die Erste der beiden erzeugten Zufallszahlen
* zurück.
*
* @returns double - eine standard normal verteilte
* Zufallszahl
*/
public double getFirstRandom()
{ return firstRandom; }
/**
* Gibt die Zweite der beiden erzeugten Zufalls-
* Zahlen zurück.
*
* @returns double - eine standard normal
* verteilte Zufallszahl
*/
public double getSecondRandom()
{ return secondRandom; }
}
} |