为所有可能的数字生成随机Int32

时间:2012-07-08 07:46:59

标签: c# random

如果我想为Int32可能包含的所有可能数字生成一个随机数,那么以下代码是否合理?有什么理由可能不是一个好主意吗? (即,均匀分布至少与Random.Next()本身一样好)

    public static int NextInt(Random Rnd) //-2,147,483,648 to 2,147,483,647
    {
         int AnInt;
         AnInt = Rnd.Next(System.Int32.MinValue, System.Int32.MaxValue);
         AnInt += Rnd.Next(2);
         return AnInt;
    }

4 个答案:

答案 0 :(得分:3)

您可以使用Random.NextBytes获取4个字节,然后使用BitConverter.ToInt32将这些字节转换为int

类似的东西:

byte[] buf = new byte[4];
Rnd.NextBytes(buf);
int i = BitConverter.ToInt32(buf,0);

答案 1 :(得分:2)

您提出的解决方案会略微扭曲分布。 minValue和maxValue的出现频率低于内部值。例如,假设int的MinValue为-2,MaxValue为1.以下是可能的初始值,每个值后跟Random(2)后的结果值:

-2: -2 -1
-1: -1  0
 0:  0  1

负-2值的一半将被修改为-1,并且只有0的一半将被修改为1.因此值-2和1将比-1和0更少发生。

达米恩的解决方案很好。另一个选择是:

if (Random(2) == 0) {
    return Random(int.MinValue, 0);
} else {
    return 1 + Random(-1, int.MaxValue);
}

另一种解决方案,类似于Damiens方法,并且比之前的方法更快

 int i = r.Next(ushort.MinValue, ushort.MaxValue + 1) << 16;
 i |= r.Next(ushort.MinValue, ushort.MaxValue + 1);

答案 2 :(得分:0)

uniform distribution并不意味着您只需获得一次。为此,您需要permutation

现在,如果您需要随机排列所有 40亿个数字,那么您有点卡住了。 .NET不允许对象大于2GB。你可以解决这个问题,但我认为这不是你真正需要的。

如果您没有重复的数字(例如,100或500万,少于几十亿),您应该这样做:

保持一组整数,从空开始。选择一个随机数。如果它已经在集合中,请选择另一个随机数。如果它不在集合中,请添加并返回。

这样你就可以保证每个号码只返回一次。

答案 3 :(得分:0)

我有一个类,我将随机字节放入8KB缓冲区,并通过从随机字节转换它们来分配数字。这为您提供了完整的int分发。 8KB缓冲区用于您不需要为每个新的随机字节[]。

调用NextBytes
    // Get 4 bytes from the random buffer and cast to int (all numbers equally this way 
    public int GetRandomInt()
    {
        CheckBuf(sizeof(int));
        return BitConverter.ToInt32(_buf, _idx);
    }

    // Get bytes for your buffer. Both random class and cryptoAPI support this
    protected override void GetNewBuf(byte[] buf)
    {
        _rnd.NextBytes(buf);
    }

    // cyrptoAPI does better random numbers but is slower
    public StrongRandomNumberGenerator()
    {
        _rnd = new RNGCryptoServiceProvider();
    }