123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- using System;
- namespace TBL.CSharp.Utilities.Random.Generator
- {
- /// <summary>
- /// 高斯随机数发生器
- /// <para>需要正态分布的随机数序列时,适用此设施</para>
- /// <para>内部使用 <see cref="SimpleGenerator"/> 作为辅助熵</para>
- /// </summary>
- public class GaussianGenerator : IRandom<GaussianGenerator.Seed>
- {
- /// <summary>
- /// 种子值
- /// </summary>
- private int _seed;
- /// <summary>
- /// 辅助熵
- /// </summary>
- private readonly SimpleGenerator _random;
- /// <summary>
- /// 已经生成的随机数计数
- /// </summary>
- private long _numberGenerated;
- /// <summary>
- /// 下一个高斯随机数
- /// </summary>
- private double _nextGaussian;
- /// <summary>
- /// 是否使用末项
- /// </summary>
- private bool _useLast = true;
- /// <summary>
- /// 从种子构造
- /// </summary>
- /// <param name="seed">种子值</param>
- 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();
- }
- /// <summary>
- /// Box Muller 算法
- /// </summary>
- 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;
- }
- /// <summary>
- /// Box Muller 算法
- /// </summary>
- private double BoxMuller(double mean, double standardDeviation) => mean + BoxMuller() * standardDeviation;
- /// <summary>
- /// 种子
- /// </summary>
- public readonly struct Seed
- {
- /// <summary>
- /// 种子值
- /// </summary>
- public readonly int SeedValue;
- /// <summary>
- /// 已经生成的随机数计数
- /// </summary>
- public readonly long NumberGenerated;
- /// <summary>
- /// 构造
- /// </summary>
- public Seed(int seed, long numberGenerated)
- {
- SeedValue = seed;
- NumberGenerated = numberGenerated;
- }
- }
- }
- }
|