当前位置:  开发笔记 > 编程语言 > 正文

如何从随机字节数组值中获取随机双值?

如何解决《如何从随机字节数组值中获取随机双值?》经验,为你挑选了2个好方法。

我想使用RNGCryptoServiceProvider作为随机数的来源.因为它只能将它们作为字节值数组输出,如何将它们转换为0到1的双精度值,同时保持结果的一致性?



1> Mehrdad Afsh..:
byte[] result = new byte[8];
rng.GetBytes(result);
return (double)BitConverter.ToUInt64(result,0) / ulong.MaxValue;


@ bruce965**第一个问题:**这是因为`ulong.MaxValue`是分子中可以得到的最大数字.**第二个问题:**不,因为分子总是正的(它是无符号的).**第三个问题:**不知道你在谈论什么......"3"与任何事情有什么关系?`2 ^ 64`比`double.MaxValue`小得多,所以没有`Infinity`和唯一可能成为'NaN`的方法是分母是零,它不是.**编辑:**也许你认为演员`double`是blitting?事实并非如此.

2> John Leidegr..:

我就是这样做的.

private static readonly System.Security.Cryptography.RNGCryptoServiceProvider _secureRng;
public static double NextSecureDouble()
{
  var bytes = new byte[8];
  _secureRng.GetBytes(bytes);
  var v = BitConverter.ToUInt64(bytes, 0);
  // We only use the 53-bits of integer precision available in a IEEE 754 64-bit double.
  // The result is a fraction, 
  // r = (0, 9007199254740991) / 9007199254740992 where 0 <= r && r < 1.
  v &= ((1UL << 53) - 1);
  var r = (double)v / (double)(1UL << 53);
  return r;
}

巧合的9007199254740991 / 9007199254740992 is ~= 0.99999999999999988897769753748436是,该Random.NextDouble方法将返回最大值(参见https://msdn.microsoft.com/en-us/library/system.random.nextdouble(v=vs.110).aspx).

通常,连续均匀分布的标准偏差是(max-min)/ sqrt(12).

样本大小为1000,我可以在2%的误差范围内可靠地获得.

样本大小为10000我可靠地获得1%的误差范围.

以下是我验证这些结果的方法.

[Test]
public void Randomness_SecureDoubleTest()
{
  RunTrials(1000, 0.02);
  RunTrials(10000, 0.01);
}

private static void RunTrials(int sampleSize, double errorMargin)
{
  var q = new Queue();

  while (q.Count < sampleSize)
  {
    q.Enqueue(Randomness.NextSecureDouble());
  }

  for (int k = 0; k < 1000; k++)
  {
    // rotate
    q.Dequeue();
    q.Enqueue(Randomness.NextSecureDouble());

    var avg = q.Average();

    // Dividing by n?1 gives a better estimate of the population standard
    // deviation for the larger parent population than dividing by n, 
    // which gives a result which is correct for the sample only.

    var actual = Math.Sqrt(q.Sum(x => (x - avg) * (x - avg)) / (q.Count - 1));

    // see http://stats.stackexchange.com/a/1014/4576

    var expected = (q.Max() - q.Min()) / Math.Sqrt(12);

    Assert.AreEqual(expected, actual, errorMargin);
  }
}

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有