填充间隔的随机数生成器

时间:2010-02-17 12:57:18

标签: algorithm language-agnostic random

如何实现一个随机数生成器,给定一个时间间隔(随机)生成该时间间隔内的所有数字,而不重复?

它应该消耗尽可能少的时间和内存。

刚刚发明的C#-ruby-ish伪代码中的示例:

interval = new Interval(0,9)
rg = new RandomGenerator(interval);
count = interval.Count // equals 10
count.times.do{
    print rg.GetNext() + " "
}

这应输出如下内容:

1 4 3 2 7 5 0 9 8 6 

8 个答案:

答案 0 :(得分:13)

使用间隔填充数组,然后将其随机播放。

洗牌N个元素数组的标准方法是选择0到N-1之间的随机数(比如R),并用项目[N]交换项目[R]。然后从N中减去一个,并重复直到达到N = 1.

答案 1 :(得分:4)

之前已经出现过。尝试使用linear feedback shift register

答案 2 :(得分:1)

一个建议,但它是内存密集型的:

生成器构建一个区间中所有数字的列表,然后将其洗牌。

答案 3 :(得分:1)

偶尔对shuffle方法的有用替代方法是使用可订阅集合容器。在每个步骤中,选择随机数0< = n<计数。从集合中提取第n个项目。

主要问题是典型的容器无法有效处理。我已经将它用于位向量,但只有当最大可能成员相当小时,它才能正常工作,因为找到第n个设置位所需的位向量的线性扫描。

99%的时间,最好的方法是像其他人建议的那样洗牌。

修改

我错过了一个简单的数组是一个很好的“设置”数据结构的事实 - 不要问我为什么,我以前用过它。 “技巧”是你不关心数组中的项是否排序。在每个步骤中,您随机选择一个并提取它。要填充空槽(无需将平均一半的项目向下移动一步),只需将当前结束项目以恒定时间移动到空槽中,然后将数组大小减小一个。

例如......

class remaining_items_queue
{
  private:
    std::vector<int>  m_Items;

  public:
    ...

    bool Extract (int &p_Item);  //  return false if items already exhausted
};

bool remaining_items_queue::Extract (int &p_Item)
{
  if (m_Items.size () == 0)  return false;

  int l_Random = Random_Num (m_Items.size ());
    //  Random_Num written to give 0 <= result < parameter

  p_Item = m_Items [l_Random];

  m_Items [l_Random] = m_Items.back ();
  m_Items.pop_back ();
}

技巧是获得一个随机数生成器,它给出(合理均匀分布)0到n-1范围内的数字,其中n每次都可能不同。大多数标准随机发生器给出固定范围。虽然以下不会给出均匀分布,但通常足够好......

int Random_Num (int p)
{
  return (std::rand () % p);
}

std :: rand返回范围0&lt; = x&lt;的随机值RAND_MAX,其中RAND_MAX是实现定义的。

答案 4 :(得分:1)

一种非常有效的方法来混合每个索引唯一的数字数组来自图像处理,并在应用像像素溶解等技术时使用。

基本上,您从有序的2D数组开始,然后移动列和行。这些排列很容易实现,你甚至可以使用一个精确的方法,在n个排列之后产生x,y的结果值。

在3x3网格上描述的基本技术:

1)从有序列表开始,每个号码只能存在一次

0 1 2
3 4 5
6 7 8

2)选择要随机播放的行/列,将其前进一步。在这种情况下,我将第二行向右移动。

0 1 2
5 3 4
6 7 8

3)选择一个你想要随机播放的行/列...我将第二列填满一个。

0 7 2
5 1 4
6 3 8

4)选择...例如,第一行,左边一个。

2 0 7
5 1 4
6 3 8

您可以根据需要随时重复这些步骤。您也可以在一维数组上进行此类转换。所以你的结果现在是[2,0,7,5,1,4,6,3,8]。

答案 5 :(得分:0)

  1. 获取区间中的所有数字,将它们放入列表/数组
  2. Shuffle列表/数组
  3. 循环列表/数组

答案 6 :(得分:0)

一种方法是在您的示例中生成有序列表(0-9)。

然后使用随机函数从列表中选择一个项目。从原始列表中删除该项目并将其添加到新列表的尾部。

当原始列表为空时,该过程结束。

输出新列表。

答案 7 :(得分:0)

您可以使用linear congruential generator随机选择的参数,以便生成完整的句号。您需要小心,因为随机数的质量可能很差,具体取决于参数。