namespace TestProject;
/// <summary>
/// 가우스 난수기
/// </summary>
public sealed class GaussianRandom
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 난수기
/// </summary>
private readonly Random random;
/// <summary>
/// 편차 보유 여부
/// </summary>
private bool hasDeviation;
/// <summary>
/// 저장 편차
/// </summary>
private double storedDeviation;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - GaussianRandom(random)
/// <summary>
/// 생성자
/// </summary>
/// <param name="random">난수기</param>
public GaussianRandom(Random random = null)
{
this.random = random ?? new Random();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 다음 가우스 난수 구하기 - NextGaussian(mean, standardDeviation)
/// <summary>
/// 다음 가우스 난수 구하기
/// </summary>
/// <param name="mean">평균</param>
/// <param name="standardDeviation">표준 쳔차</param>
/// <returns>다음 가우스 난수</returns>
public double NextGaussian(double mean = 0, double standardDeviation = 1)
{
if(standardDeviation <= 0)
{
throw new ArgumentOutOfRangeException("standardDeviation", "Must be greater than zero.");
}
if(this.hasDeviation)
{
this.hasDeviation = false;
return this.storedDeviation * standardDeviation + mean;
}
double randomValue1;
double randomValue2;
double rSquared;
do
{
randomValue1 = 2 * this.random.NextDouble() - 1;
randomValue2 = 2 * this.random.NextDouble() - 1;
rSquared = randomValue1 * randomValue1 + randomValue2 * randomValue2;
}
while(rSquared >= 1 || rSquared == 0);
double polarTransformationValue = Math.Sqrt(-2 * Math.Log(rSquared) / rSquared);
this.storedDeviation = randomValue2 * polarTransformationValue;
this.hasDeviation = true;
return randomValue1 * polarTransformationValue * standardDeviation + mean;
}
#endregion
}