假设我有一个随机数生成器,它在[0, RAND_MAX]
和内生成一个数字RAND_MAX < UINT_MAX
。
如何在 和 内生成一个随机数,[0, i]
同时保持均匀分布,并且不超过任何计算?i>RAND_MAX
i<UINT_MAX
UINT_MAX
第一次尝试是将范围分成n
相等的部分,以便i mod n == 0
通过找到最小分母i
(使用整数分解筛算法之一)。每个子列表具有相等的分布,可以随机选择任何一个。如果i
是素数,则失败:
0 1 2 3 4 5 6
|___| |_____|
第二种尝试是将范围分成两部分a = [0, floor(i/2)]
和b = [floor(i/2)+1, i]
,然后将分布计算为两个子范围的长度之比:
g = gcd(length(a), length(b))
if random(0, length(a)/g + length(b)/g - 1) >= length(a)/g
random(0, floor(i/2))
else
random(floor(i/2)+1, i)
给定以下范围,选择右侧子范围的频率是左侧子范围的两倍:
0 1 2 3 4 5
|_| |_____|
不幸的是,如果第一次调用random()
可能会永远递归gcd()
。
最后的尝试是纠正通过拆分奇数长度范围引入的分布偏斜:
if random(1)
if random(1)
random(0, floor(i/2))
else
random(floor(i/2) + 1, i)
else
if random(1)
random(0, floor(i/2) - 1)
else
random(floor(i/2), i)
这可能行不通。
编辑:
对于任何有类似问题的人,两个统一变量的总和遵循三角分布(请参阅Irwin-Hall 分布)。这是无效的:
# triangular distribution:
random(a, floor(b/2)) + random(a, b - floor(b/2))
编辑(接受):
我考虑的两个答案都是高质量的。此答案以每位或每位为基础考虑 RNG。接受的答案以数字方式考虑 RNG,而不考虑数字或位。在这两种情况下,阅读评论都很重要。
我还发布了一个后续问题维护跨子范围的均匀分布。