我想按排序顺序生成一个随机选择的正整数的序列化列表,但是在给定的用例中,所需的整数数量和它可以选择的数字范围很容易达到数百万(或者有时甚至每个都在数十亿的范围内,如果正在使用64位整数),所以将数字存储到数组中然后可以由软件随机访问是不可行的。
因此,我想通过一个看起来像这样的简单循环来生成数字:
unsigned current = 0;
while(remaining>0) {
if (find_next_to_output(current,max,remaining)) {
// do stuff having output a value
}
}
其中remaining
初始化为我打算输出的多个随机数,max
是可能生成的数字的上限(加1)。可以假设remaining
将始终初始化为小于或等于max
的数字。
find_next_to_output函数看起来类似于:
/**
* advance through the range of accepted values until all values have been output
* @param current [in/out] integer to examine. Advances to the next integer
* to consider for output
* @param max one more than the largest integer to ever output
* @param remaining [in/out] number of integers left to output.
* @return true if the function ouputted an integer, false otherwise
*/
bool find_next_to_output(unsigned ¤t, unsigned max, unsigned &remaining)
{
bool result = false;
if (remaining == 0) {
return false;
} if (rnd() * (max - current) < remaining) {
// code to output 'current' goes here.
remaining--;
result = true;
}
int x = ?; // WHAT GOES HERE?
current += x;
return result;
}
注意,上面使用的函数rnd()
将在[0..1]范围内返回一个随机生成的统一浮点数。
正如评论所强调的那样,我不确定如何计算x
的合理值,以便函数跳过的current
值的数量反映了没有一个被跳过的值会被选中(同时仍留下足够的数字,仍然可以选择所有剩余的数字)。我知道它需要是一个随机数(可能不是来自均匀分布),但我不知道如何为它计算一个好的值。在最坏的情况下,它每次只会增加current
,但是当剩余输出的整数与剩余范围内的整数之间存在足够的差异时,这在统计上应该是不可能的。
我不想使用任何第三方库,例如boost,尽管我可以使用任何可能打包在C ++ 11标准库中的随机数生成器。
如果我的问题的任何部分不清楚,请在下面评论,我会尽力澄清。
答案 0 :(得分:1)
如果我理解正确,您希望生成随机的升序数字。您正尝试通过创建随机大小的步骤来添加到上一个数字。
您担心的是,如果步骤太大,那么您将溢出并回绕,从而打破上升的要求。
x
需要以防止溢出的方式进行约束,同时仍满足随机要求。
您需要modulo
运算符(模数)。 %
const unsigned step = (max - current) / remaining;
x = unsigned(rnd() * max) % step; // will never be larger than step