我如何快速和安全地 *确定0
(含)到r
范围内的随机数(不包括)?
换句话说,拒绝采样的优化版本:
u32 myrand(u32 x)
{
u32 ret = rand();
while(ret >= x)
ret = rand();
return(ret);
}
*安全地说,我的意思是统一分布。
答案 0 :(得分:6)
如果您希望对结果进行统一分布,则拒绝抽样是可行的方法。众所周知,做任何更聪明的事情是很困难的。例如,使用模运算符会导致任何不是2的幂的数字的结果值分布不均。
然而,您发布的算法可以通过丢弃不必要的最高有效位来改进。 (见下文。)
This is how标准Java API实现Random.nextInt(int n)
:
public int nextInt(int n) {
[...]
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
在你们的共识中你可以读到:
算法有点棘手。它拒绝会导致分布不均匀的值(由于2 31 不能被 n 整除)。值被拒绝的概率取决于n。最坏的情况是 n = 2 30 +1,其中拒绝的概率是1/2,并且循环终止之前的预期迭代次数是2。
答案 1 :(得分:-1)
u32 myrand(u32 x)
{
return rand() % (x+1);
}
由于问题已被更改为包含均匀分布,因此需要更多类似的内容:
u32 myrand(u32 x)
{
assert(x <= RAND_MAX && x > 0);
int numOfRanges = (RAND_MAX % x);
int maxAcceptedRand = numOfRanges * x;
int randNumber;
do
{
randNumber = rand();
}
while(randNumber <= maxAcceptedRand);
return number / numOfRanges;
}