如何在0和1之间生成加密安全的Double?

时间:2010-05-18 03:45:39

标签: c# random

我知道如何使用伪随机数生成器的NextDouble方法生成0到1之间的随机数。

var rng1 = new System.Random();
var random1 = rng1.NextDouble(); // generates a random double between 0 and 1.0

我知道如何使用加密安全随机数生成器填充随机字节数组。

Byte[] bytes = new Byte[8];
var rng2 = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng2.GetBytes(bytes); // generates 8 random bytes

但是如何将RNGCryptoServiceProvider的字节数组输出转换为在0(包括)和1(不包括)之间均匀分布的随机数?

2 个答案:

答案 0 :(得分:24)

在我看来,到目前为止,由于采取相反的方法,解决方案将具有不均匀的分布。为了均匀分布,我认为你想要这样的东西。

// Step 1: fill an array with 8 random bytes
var rng = new RNGCryptoServiceProvider();
var bytes = new Byte[8];
rng.GetBytes(bytes);
// Step 2: bit-shift 11 and 53 based on double's mantissa bits
var ul = BitConverter.ToUInt64(bytes, 0) / (1 << 11);
Double d = ul / (Double)(1UL << 53);

请注意,您不能将UInt64划分为UInt64.MaxValue,因为double没有足够的位,并且无法为所有输入获取唯一输出。所以你可以/必须扔掉一些东西。

答案 1 :(得分:1)

好吧,我不会将64位随机数称为“加密安全” - 你需要比“加密安全”更多的位。但无论如何,你可以这样做:

var bytes = // assume this contains 8 bytes of random numbers

long l = BitConverter.ToInt64(bytes);
double d = Math.Abs(1 / (double)l);