GaussianGenerator.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. namespace TBL.CSharp.Utilities.Random.Generator
  3. {
  4. /// <summary>
  5. /// 高斯随机数发生器
  6. /// <para>需要正态分布的随机数序列时,适用此设施</para>
  7. /// <para>内部使用 <see cref="SimpleGenerator"/> 作为辅助熵</para>
  8. /// </summary>
  9. public class GaussianGenerator : IRandom<GaussianGenerator.Seed>
  10. {
  11. /// <summary>
  12. /// 种子值
  13. /// </summary>
  14. private int _seed;
  15. /// <summary>
  16. /// 辅助熵
  17. /// </summary>
  18. private readonly SimpleGenerator _random;
  19. /// <summary>
  20. /// 已经生成的随机数计数
  21. /// </summary>
  22. private long _numberGenerated;
  23. /// <summary>
  24. /// 下一个高斯随机数
  25. /// </summary>
  26. private double _nextGaussian;
  27. /// <summary>
  28. /// 是否使用末项
  29. /// </summary>
  30. private bool _useLast = true;
  31. /// <summary>
  32. /// 从种子构造
  33. /// </summary>
  34. /// <param name="seed">种子值</param>
  35. public GaussianGenerator(int seed)
  36. {
  37. _seed = seed;
  38. _random = new SimpleGenerator(seed);
  39. }
  40. public int NextRaw()
  41. {
  42. _numberGenerated++;
  43. const double num1 = 3.5;
  44. var num2 = (int)BoxMuller(0 + int.MaxValue / 2.0, int.MaxValue / 2.0 / num1);
  45. return num2;
  46. }
  47. public Seed DumpSeed() => new Seed(_seed, _numberGenerated);
  48. public void RestoreBySeed(Seed seed)
  49. {
  50. _seed = seed.SeedValue;
  51. _random.RestoreBySeed(new SimpleGenerator.Seed(seed.SeedValue));
  52. _numberGenerated = 0L;
  53. _nextGaussian = 0.0;
  54. _useLast = true;
  55. for (long index = 0; index < seed.NumberGenerated; ++index)
  56. this.Next();
  57. }
  58. /// <summary>
  59. /// Box Muller 算法
  60. /// </summary>
  61. private double BoxMuller()
  62. {
  63. if (_useLast)
  64. {
  65. _useLast = false;
  66. return _nextGaussian;
  67. }
  68. double num1;
  69. double num2;
  70. double d;
  71. do
  72. {
  73. num1 = 2.0 * _random.NextDouble() - 1.0;
  74. num2 = 2.0 * _random.NextDouble() - 1.0;
  75. d = num1 * num1 + num2 * num2;
  76. } while (d >= 1.0 || d == 0.0);
  77. double num3 = Math.Sqrt(-2.0 * Math.Log(d) / d);
  78. _nextGaussian = num2 * num3;
  79. _useLast = true;
  80. return num1 * num3;
  81. }
  82. /// <summary>
  83. /// Box Muller 算法
  84. /// </summary>
  85. private double BoxMuller(double mean, double standardDeviation) => mean + BoxMuller() * standardDeviation;
  86. /// <summary>
  87. /// 种子
  88. /// </summary>
  89. public readonly struct Seed
  90. {
  91. /// <summary>
  92. /// 种子值
  93. /// </summary>
  94. public readonly int SeedValue;
  95. /// <summary>
  96. /// 已经生成的随机数计数
  97. /// </summary>
  98. public readonly long NumberGenerated;
  99. /// <summary>
  100. /// 构造
  101. /// </summary>
  102. public Seed(int seed, long numberGenerated)
  103. {
  104. SeedValue = seed;
  105. NumberGenerated = numberGenerated;
  106. }
  107. }
  108. }
  109. }