将随机字节转换为指定范围内的整数

本文关键字:范围内 整数 随机 字节 转换 | 更新日期: 2023-09-27 18:34:09

我正在尝试编写一个函数,该函数使用默认的随机数生成器实现来生成指定范围内的 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 的同时手动执行此操作感兴趣。

将随机字节转换为指定范围内的整数

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();

结果在 0300 之间的所有数字中都是非常随机的,min.count = 3301max.count = 3358 .