生成没有重复的随机序列

时间:2010-10-05 13:39:37

标签: algorithm random sequence

我在这里读了几篇关于生成没有重复的随机序列的帖子(例如Create Random Number Sequence with No Repeats),并决定根据自己的需要实现它

实际上,这是一种算法,它使用当前计数器的某些位来应用一些非破坏性(可逆)操作,以便获得一个只应出现一次的伪随机数。由于操作是可逆的,因此不同的源编号将给出不同的结果编号。

至少有几种操作可能,例如交换两位,反转一位,循环移位。如果我们只使用上面提到的那些,那么序列的质量将不会很好,因为附近的计数器将产生具有相似数量的零和1的结果。真正的游戏改变者是xor一点一点。现在序列看起来好多了,但问题是:

  • 是否有足够的操作子集(例如将位+ xor位反转另一位)并添加任何其他只会使算法更难以阅读而不会带来额外的好处
  • 我如何近似猜测给定范围的操作次数,以使序列足够好。例如,对于从0到31的数字的200次操作给出了视觉上良好的结果,但是对于范围0..199的200次操作有时会给出接近数字的块。
  • 是否有用于测试此类序列的算法或测试套件。我知道并且曾经使用过可以测试一般随机序列的套件,但是这个是不同的,所以可能需要一些特殊的套件,或者至少有一些转换回一般的随机世界

更新:正如我在此处发表的评论中所述,已经存在这样的生成器:AES加密,但不幸的是它只能用于128位范围。

由于

最高

2 个答案:

答案 0 :(得分:2)

<强>问题:

生成1到N之间的唯一随机整数列表。

<强>解决方案:

  1. 生成N个随机数;高斯或制服...
  2. 对它们进行排序;保存索引(即列表中每个值的位置)
  3. 排序索引是您的清单。
  4. 在Matlab中:

    z = rand( [N 1] );
    [dummy iz] = sort(z);
    

    %iz是你的清单。

答案 1 :(得分:1)

除非你有充分的理由,否则你不想重新发明伪随机生成。很可能会出错。我建议从A [i] = i

的数组开始

然后这样做:

for (i=0; i< n; i++) {
  j = random_number_between(i,n-1);
  swap(A[i],A[j]);
}

修改 这是对以下评论的回应:

您希望序列的随机性如何。注意,随机选择的排列中的固有信息是log(n!),其接近n / e位。因此,您确实需要生成许多随机位。既然你想要在我认为的任何地方存储这些许多随机比特(更像是一种直觉而不是数学证据),如果没有那么多的存储,就很难做出真正的随机排列。

但是如果你只想要一个不容易逆向工程的序列,你可以一个接一个地连接多个1:1函数。 我想到两件事:   - 保持计数器i的顺序为0到N-1。

  • 在i上执行log_2(N / 2)位翻转,当你开始序列时,随机选择要翻转的位。

  • 使用上述方法在序列开头的log_2(N)位上生成随机置换,然后交换上面结果中的位。

  • 求一个随机数r1,它是n at的相对素数,另一个是0和n-1之间的随机数r2。你的第i个数字是= r2 ^ r%n。

这些的一些组合应该给你一个难以逆向工程序列。关键是你注入的随机位越多,就越难以进行逆向工程。

我想到的一件事是,如果您的范围是0..N-1,只需找到一个大数P,它是N的相对素数并选择另一个随机数