如何使用RNGCryptoServiceProvider获得大于256的随机数?
码:
private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
byte[] randomNumber = new byte[1];
//Fill the array with a random value.
rngCsp.GetBytes(randomNumber);
Run Code Online (Sandbox Code Playgroud)
填充1到8个字节的数组,并使用BitConverter提取整数.
static ulong RandomUInt64()
{
var rng = new RNGCryptoServiceProvider();
var bytes = new byte[8];
rng.GetBytes(bytes);
return BitConverter.ToUInt64(bytes);
}
Run Code Online (Sandbox Code Playgroud)
如果要生成特定范围内的随机数并且还想保留分布,则应生成一系列数字并丢弃不在预期范围内的值(蒙特卡罗方法).我怀疑如果你正在考虑一个安全的加密随机数生成器,这就是你想要的行为.
static int Random(RandomNumberGenerator rng, int min, int max)
{
if (min > max) throw new ArgumentException(nameof(min));
if (min == max) return min;
var bytes = new byte[4];
long diff = max - min;
while (true)
{
rng.GetBytes(bytes);
var rand = BitConverter.ToUInt32(bytes);
var remainder = (1 + (long) uint.MaxValue) % diff;
if (rand < max - remainder)
{
return (int) (min + (rand % diff));
}
}
}
Run Code Online (Sandbox Code Playgroud)
调用提供程序时会产生很大的开销,因此请考虑缓冲对GetBytes的调用.要更快地生成数字,您还可以从随机缓冲区中选择最多日志(范围)/ log(2)位,此外还要丢弃超出范围的样本(以保留分布).
public class RandomGenerator
{
private readonly RandomNumberGenerator _rng;
public RandomGenerator(RandomNumberGenerator rng)
{
_rng = rng;
}
public IEnumerable<int> Next(ulong range)
{
var buffer = new byte[8 * 512];
var bits = (int) Math.Ceiling(Math.Log(range) / Math.Log(2));
var mask = (ulong) ~(~0 << bits);
while (true)
{
_rng.GetBytes(buffer);
for (var i = 0; i < buffer.Length / 8; i += 8)
{
var num = BitConverter.ToUInt64(buffer, i);
var n = num & mask;
if (n <= range - 1)
{
yield return (int) n;
}
}
}
}
public IEnumerable<int> Next(int min, int max)
{
if (min > max) throw new ArgumentOutOfRangeException(nameof(min));
var range = (ulong) Math.Abs(max - min);
return Next(range).Select(r => r + min);
}
}
Run Code Online (Sandbox Code Playgroud)
这将为您提供有用的API:
var rng = new RNGCryptoServiceProvider();
var random = new RandomGenerator(rng);
var randomValues = random.Next(-1000, 1000).Take(100).ToArray();
Run Code Online (Sandbox Code Playgroud)