我正在尝试编写一个函数,该函数使用默认的RandomNumberGenerator实现来生成指定范围内的Int32值。
void GenerateRandom (int [] data, int minInclusive, int maxExclusive)
{
int size = 0;
int length = 0;
byte [] bytes = null;
size = (int) Math.Ceiling(Math.Log(Math.Abs(maxExclusive - minInclusive), 2));
length = data.Length * size;
var bytes = new byte [length];
using (RandomNumberGenerator generator = RandomNumberGenerator.Create())
{
generator.GetBytes(bytes);
}
// How to effectively convert this `byte []` to an `int []` within the specified range?
}
一种尝试是生成长度为(data.Length * ((int) Math.Ceiling(Math.Log(Math.Abs(maxExclusive - minInclusive), 2))))
的随机字节数组,并将每个x个字节组合成一个int。无论指定的范围如何,这种方法当然具有向较大值偏移的巨大缺点,因为多个最重要的字节几乎不可能为零。
任何输入都将不胜感激。虽然我在这里使用.NET,但平台/语言并不重要。寻找概念暗示。
请注意,我已经熟悉.NET中的Random类,但我只想知道如何在能够使用RandomNumberGenerator的情况下手动执行此操作。
答案 0 :(得分:1)
unsafe static int[] GenerateRandom(int length, int minInclusive, int maxExclusive)
{
var bytes = new byte[length * 4];
var ints = new int[length];
var ratio = uint.MaxValue / (double)(maxExclusive - minInclusive);
using (RandomNumberGenerator generator = RandomNumberGenerator.Create())
{
generator.GetBytes(bytes);
fixed(byte* b = bytes)
{
uint* i = (uint*)b;
for(int j = 0; j < length; j++, i++)
{
ints[j] = minInclusive + (int)(*i / ratio);
}
}
}
return ints;
}
我做了一点测试:
var ints = GenerateRandom(1000000, 0, 300);
var groups = ints.GroupBy(x => x).Select(g => new { value = g.Key, count = g.Count() });
var hist = Enumerable.Range(0, 300).Join(groups, x => x, g => g.value, (x, g) => new { value = x, count = g.count }).ToList();
var max = hist.OrderByDescending(x => x.value).First();
var min = hist.First();
0
和300
与min.count = 3301
和max.count = 3358
之间的所有数字的结果非常随机。