范围内的随机数,概率相等

时间:2012-04-16 17:32:56

标签: c# random range prng

这可能比C#更加数学相关,但我需要一个C#解决方案,所以我把它放在这里。

我的问题是关于随机数生成器的概率,更具体地说,如果每个可能的值以相同的概率返回。

我知道有Random.Next(int, int)方法在第一个整数和最后一个整数之间返回一个数字(最后一个是独占的)。

Random.Next() [不重载]将返回介于0和Int32.MaxValue(即2147483647)之间的值 - 1,所以2147483646。

如果我想要1到10之间的值,我可以调用Random.Next(1, 11)来执行此操作,但是1到10之间的每个值是否都有相同的概率发生?

例如,范围是10,因此2147483646不能完全被10整除,因此值1-6的概率稍高(因为2147483646 % 10 = 6)。这当然假设Random.Next() [没有重载]内的每个值都以相等的概率返回0到2147483646之间的值。

如何确保范围内的每个数字具有相同的发生概率?让我们说一个彩票类型系统,对某些人来说比其他人有更高的可能性是不公平的,我不是说我会使用内置的RN#C#,我只是以它为例。

4 个答案:

答案 0 :(得分:16)

我注意到在你的帖子中没有人真正回答过这个问题:

  

例如,范围是10,因此2147483646不能完全被10整除,因此值1-6具有稍高的发生概率(因为2147483646%10 = 6)。这当然是假设Random.Next()[without overloads]中的每个值都以相等的概率返回0到2147483646之间的值。

     

如何确保范围内的每个数字具有相同的发生概率?

是的,所以你只丢掉导致不平衡的值。例如,假设您有一个可以在{ 0, 1, 2, 3, 4 }上生成均匀分布的RNG,并且您希望使用它来生成{ 0, 1 }上的均匀分布。天真的实现是:从{0, 1, 2, 3, 4}绘制,然后返回值% 2;然而,这显然会产生偏差的样本。发生这种情况是因为,正如您所注意到的,5(项目数)不能被2整除。因此,抛出任何产生值4的绘制。因此,算法将是

 draw from { 0, 1, 2, 3, 4 }
 if the value is 4, throw it out
 otherwise, return the value % 2

您可以使用此基本思想来解决一般问题。

  

然而,1到10之间的每个值都有相同的发生概率吗?

是的,确实如此。来自MSDN

  

从一组有限的数字中选择具有相等概率的伪随机数。

编辑:显然,文档与.NET中的当前实现不一致。文档说明抽奖是统一的,但代码表明它不是。但是,这并不能否定这是一个可解决的问题,我的方法是解决它的一种方法。

答案 1 :(得分:9)

正如您所期望的那样,内置于RNG中的C#是均匀分布的。根据您为Next(min, max)指定的范围,每个数字都有相同的可能性。

你可以自己测试一下(我有),比如说,拿1M个样本并存储每个数字实际出现的次数。如果你绘制它,你会得到一条几乎是平线的曲线。

另请注意,每个具有相同可能性的数字并不意味着每个数字都会出现相同的次数。如果您正在查看1到10之间的随机数,则为100迭代,它不会是每个数字10次出现的均匀分布。有些数字可能会出现8次,有些则可能出现12次或13次。但是,随着迭代次数的增加,这往往会有所偏差。

此外,由于在评论中提及,我将补充:如果你想要更强大的东西,请查找加密PRNG。 Mersenne Twister特别擅长于我所看到的(快速,便宜到计算,时间很长),它在C#中有开源实现。

答案 2 :(得分:9)

测试程序:

var a = new int[10];
var r = new Random();
for (int i = 0; i < 1000000; i++) a[r.Next(1, 11) - 1]++;
for (int i = 0; i < a.Length; i++) Console.WriteLine("{0,2}{1,10}", i + 1, a[i]);

输出:

 1      99924
 2     100199
 3     100568
 4     100406
 5     100114
 6      99418
 7      99759
 8      99573
 9     100121
10      99918

结论:

以相等的概率返回每个值。

答案 3 :(得分:3)

灰烬和dtb不正确:你怀疑某些数字比其他数字发生的可能性更大。

当您致电.Next(x, y)时,有y-x可能的返回值。 .NET 4.0 Random类根据NextDouble()的返回值计算返回值(这是一个略微简化的描述)。

显然,可能的双值集是有限的,并且,正如您所注意到的,它可能不是.Next(x, y)的可能返回值集合大小的倍数。因此,假设输入值的集合均匀分布,某些输出值的发生概率会略高。

我不知道有多少数字双值(即,排除无穷大和NaN值),但它肯定大于2 ^ 32。在您的情况下,如果我们假设2 ^ 32个值,为了参数,那么我们必须将4294967296个输入映射到10个输出。某些值可能会发生更大的概率,或者更高的0.00000023283064397913028110629%。事实上,由于输入状态的数量大于<^ em>而不是2 ^ 32,因此概率差异会更小。