我编写了以下代码来生成[0,int.MaxValue]范围内的随机数,但我不确定如何在保持均匀分布的同时将范围限制为[0,randomMax:
private static int GetNextInt32(this RNGCryptoServiceProvider random)
{
var buffer = new byte[sizeof(int)];
random.GetBytes(buffer);
return Math.Abs(BitConverter.ToInt32(buffer, 0));
}
感谢。
答案 0 :(得分:4)
这是一种方法:http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=775。请参阅标题为“创建System.Random替换”的部分。
但请注意,使用模数运算符可能不是确保良好分布的最佳方法。一种可能更好的方法是(int)(NextDouble() * (MaxValue - 1));
您的代码有一个潜在的错误。如果buffer
包含十六进制值00 00 00 80
,即int.MinValue
,Math.Abs
将引发异常。
请注意,与调用GetBytes
相比,RNGCryptoServiceProvider
上的Random.Next
调用非常慢。你最好调用GetBytes
来填充更大的缓冲区,然后从中运出随机数。我的例子说明了这是怎么做的。
答案 1 :(得分:3)
Java nextInt
documentation中有适当算法的描述。
该算法反复拒绝任何会导致分布不均匀的值并再次尝试。从理论上讲,这意味着在最坏的情况下它可以永远循环。实际上它会很快。
这是一个(完全未经测试的)C#翻译:
public static int GetNextInt32(this RNGCryptoServiceProvider rng, int maxValue)
{
if (maxValue < 1)
throw new ArgumentOutOfRangeException("maxValue", maxValue, "Value must be positive.");
var buffer = new byte[4];
int bits, val;
if ((maxValue & -maxValue) == maxValue) // is maxValue an exact power of 2
{
rng.GetBytes(buffer);
bits = BitConverter.ToInt32(buffer, 0);
return bits & (maxValue - 1);
}
do
{
rng.GetBytes(buffer);
bits = BitConverter.ToInt32(buffer, 0) & 0x7FFFFFFF;
val = bits % maxValue;
} while (bits - val + (maxValue - 1) < 0);
return val;
}
答案 2 :(得分:1)
MSDN杂志文章向您展示了如何创建使用加密RNG的Random
:
http://msdn.microsoft.com/en-us/magazine/cc163367.aspx
(这篇文章不再可以直接访问了。它来自2007年9月号,标题是“来自CryptoRandom的故事”。你必须下载存档的问题。它是.chm所以你必须解锁它来自互联网,在您阅读之前。您也可以使用互联网档案。)
答案 3 :(得分:0)
如果您不需要太多速度,也许您可以试试这个:
private static RNGCryptoServiceProvider _RNG = new RNGCryptoServiceProvider();
private static int GetNextRnd (int min, int max)
{
byte[] rndBytes = new byte[4];
_RNG.GetBytes(rndBytes);
int rand = BitConverter.ToInt32(rndBytes, 0);
const Decimal OldRange = (Decimal)int.MaxValue - (Decimal)int.MinValue;
Decimal NewRange = max - min;
Decimal NewValue = ((Decimal)rand - (Decimal)int.MinValue) / OldRange * NewRange + (Decimal)min;
return (int)NewValue;
}
这会将全范围int
数字缩放到您的值范围,保持分布。
我知道这是一个老帖子,但我遇到了类似的问题,这个灵魂对我有用。