【发布时间】:2009-12-17 03:15:59
【问题描述】:
假设我有一份奖品清单:
奖A B奖 奖品C
而且,对于他们每个人,我想从我的与会者名单中选出一名获胜者。
假设我的与会者名单如下:
用户1、用户2、用户3、用户4、用户5
从该列表中选择用户的公正方法是什么?
显然,我将使用加密安全的伪随机数生成器,但如何避免偏向列表的前面?我假设我不会使用模数?
编辑
所以,这就是我想出的:
class SecureRandom
{
private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
private ulong NextUlong()
{
byte[] data = new byte[8];
rng.GetBytes(data);
return BitConverter.ToUInt64(data, 0);
}
public int Next()
{
return (int)(NextUlong() % (ulong)int.MaxValue);
}
public int Next(int maxValue)
{
if (maxValue < 0)
{
throw new ArgumentOutOfRangeException("maxValue");
}
if (maxValue == 0)
{
return 0;
}
ulong chop = ulong.MaxValue - (ulong.MaxValue % (ulong)maxValue);
ulong rand;
do
{
rand = NextUlong();
} while (rand >= chop);
return (int)(rand % (ulong)maxValue);
}
}
注意:
Next() 在 [0, int.MaxValue] 范围内返回一个 intNext(int.MaxValue) 在 [0, int.MaxValue) 范围内返回一个 int
【问题讨论】:
-
对第 10 位进行取模,或者使用更好的随机数生成器。只要知道大小,模数有什么问题?您可以编写一个单元测试,以确保您生成的分布是体面的。但是,在一些罕见的平行宇宙中,您可以连续获得一百万个零。 ;)
-
原谅我的无知,但为什么“RNG”会有偏见?
-
不一定。使用模数会。
标签: algorithm language-agnostic random