此方法的工作原理是,每个范围代表所有范围中所有可能值总和的一小部分。如果n
是所有可能值的总数,您可以想象范围内的值分布如下:
1------10|11-----14|15---------------40|41-----49|....|(n-x)-----n
range 1 | range 2 | range 3 | range 4 |....| range n
Where 1-10
对应于范围 1 中的值,依此类推。
从那里开始,生成一个随机数就很简单了1
to n
,找出它属于哪个范围以及它对应于该范围中的哪个值。
让范围表示为元组数组,如下
ranges = [(2, 50), (500, 600), (630, 890)]
假设范围已排序并且彼此不重叠,首先我们必须找到跨越这些范围的整数总数,即我们可以生成的可能值的总数(n
)。我们将这些范围的长度存储在一个数组中lengths
。伪代码:
lengths = ranges.map(range => range.max - range.min + 1)
请注意,上面指定的映射函数仅适用于包含范围。根据您的范围类型,您可能需要更改它。另请注意n = sum(lengths)
.
Let x
是范围内的随机数1
to n
(包括的)。然后是数组索引i
其中的范围x
找到的第一个整数如下:
i = 0
while (x > lengths[i]) {
x -= lengths[i]
i++
}
在这个循环之后,x
将包含index范围内的随机数i
。也就是说,如果x
为 3,随机数是范围内的第三个数字i
.
所需的随机数由下式给出ranges[i].min + (x - 1)
.