using System;
namespace TBL.CSharp.Utilities.Random.Generator
{
///
/// 高斯随机数发生器
/// 需要正态分布的随机数序列时,适用此设施
/// 内部使用 作为辅助熵
///
public class GaussianGenerator : IRandom
{
///
/// 种子值
///
private int _seed;
///
/// 辅助熵
///
private readonly SimpleGenerator _random;
///
/// 已经生成的随机数计数
///
private long _numberGenerated;
///
/// 下一个高斯随机数
///
private double _nextGaussian;
///
/// 是否使用末项
///
private bool _useLast = true;
///
/// 从种子构造
///
/// 种子值
public GaussianGenerator(int seed)
{
_seed = seed;
_random = new SimpleGenerator(seed);
}
public int NextRaw()
{
_numberGenerated++;
const double num1 = 3.5;
var num2 = (int)BoxMuller(0 + int.MaxValue / 2.0, int.MaxValue / 2.0 / num1);
return num2;
}
public Seed DumpSeed() => new Seed(_seed, _numberGenerated);
public void RestoreBySeed(Seed seed)
{
_seed = seed.SeedValue;
_random.RestoreBySeed(new SimpleGenerator.Seed(seed.SeedValue));
_numberGenerated = 0L;
_nextGaussian = 0.0;
_useLast = true;
for (long index = 0; index < seed.NumberGenerated; ++index)
this.Next();
}
///
/// Box Muller 算法
///
private double BoxMuller()
{
if (_useLast)
{
_useLast = false;
return _nextGaussian;
}
double num1;
double num2;
double d;
do
{
num1 = 2.0 * _random.NextDouble() - 1.0;
num2 = 2.0 * _random.NextDouble() - 1.0;
d = num1 * num1 + num2 * num2;
} while (d >= 1.0 || d == 0.0);
double num3 = Math.Sqrt(-2.0 * Math.Log(d) / d);
_nextGaussian = num2 * num3;
_useLast = true;
return num1 * num3;
}
///
/// Box Muller 算法
///
private double BoxMuller(double mean, double standardDeviation) => mean + BoxMuller() * standardDeviation;
///
/// 种子
///
public readonly struct Seed
{
///
/// 种子值
///
public readonly int SeedValue;
///
/// 已经生成的随机数计数
///
public readonly long NumberGenerated;
///
/// 构造
///
public Seed(int seed, long numberGenerated)
{
SeedValue = seed;
NumberGenerated = numberGenerated;
}
}
}
}