如果我想为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;
}
答案 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();
}