从随机比特序列生成随机整数

时间:2014-08-11 02:35:36

标签: algorithm random language-agnostic integer prng

非常基本的问题,但我似乎无法在Google上找到答案。标准PRNG将生成一系列随机位。我如何使用它来产生一系列随机整数,其均匀概率分布在[0,N]范围内?此外,每个整数应使用(期望值)log_2(N)位。

5 个答案:

答案 0 :(得分:3)

如果你想要一个介于1和N之间的随机数:

  • 您可以计算将N转换为二进制数所需的位数。那是:

    n_bits = ceiling(log_2(N))
    

    天花板是"围绕"操作。 (例如:ceiling(3)= 3,ceiling(3.7)= 4)

  • 您选择随机二进制列表的前n_bits并将其更改为十进制数。

  • 如果你的十进制数高于N,那么......你丢弃它并再次尝试使用n_bits的下一位,直到它起作用。

例如N = 12:

  • n_bits = ceiling(log_2(12))= 4

  • 你取随机位序列的4个第一位,可能是" 1011"

  • 你转过" 1011"到一个十进制数字给出13.这超过12,没有好处。所以:

  • 取随机序列中的4个下一位,可能是" 1110"。

  • 转' 1110'到小数,给出7.这有效!

希望它有所帮助。

答案 1 :(得分:0)

实际上,大多数标准PRNG(如线性同余生成器或Mersenne twister)会生成整数值序列。甚至通用的反馈移位寄存器技术通常在寄存器/字级实现。我不知道任何实际在比特级操作的常用技术。这并不是说它们不存在,但它们并不常见......

生成从1到N的值通常是通过将生成的整数值取模为所需的界限,然后进行接受/拒绝阶段来确保您不受模偏差的影响。例如,请参阅Java的nextInt(int bound)方法,了解如何实现此方法。 (在结果中加1,得到[1,N]而不是[0,N-1]。)

答案 2 :(得分:0)

理论上这是可能的。找到a,b这样2 ^ a> N ^ b但非常接近。 (这可以通过迭代log2(N)的倍数来完成。)取第一个位,然后将其解释为二进制数,将其转换为基数N(同时检查该数字是否小于N ^ b)。数字给出了所需序列的b项。

问题在于转换为基数N是非常昂贵的,并且比基本上任何PRNG都要花费更多,所以这主要是理论上的答案。

答案 3 :(得分:-1)

从范围[0, N-1]开始,然后使用01来执行二分搜索:

  • 0:下半部分
  • 1:上半部分

e.g。当N = 16时,您从[0, 15]开始,序列0, 1, 1, 0将给出:

  1. [0, 7]
  2. [4, 7]
  3. [6, 7]
  4. [6]
  5. 如果N不是2的幂,则在任何迭代中,剩余数字列表的长度可能是奇数,在这种情况下,需要做出决定将中间数作为下半部分的一部分或上半部分。这可以在算法开始时确定。滚动一次:0表示包括下半部分的所有中间数字实例,1表示包括右半部分的所有中间数字实例。

    我认为这至少比你要求的统一分布更接近于生成log(N)位并采用它或取mod N的常用方法。

    为了说明我的意思,使用我的方法生成[0, 9]范围内的数字:

    To generate 0
    0: 0, 0, 0, 0
    1: 0, 0, 0
    
    To generate 1
    0: 0, 0, 0, 1
    1: 0, 0, 1
    
    To generate 2
    0: 0, 0, 1
    1: 0, 1, 0
    
    To generate 3
    0: 0, 1, 0
    1: 0, 1, 1, 0
    
    To generate 4
    0: 0, 1, 1
    1: 0, 1, 1, 1
    
    To generate 5
    0: 1, 0, 0, 0
    1: 1, 0, 0
    
    To generate 6
    0: 1, 0, 0, 1
    1: 1, 0, 1
    
    To generate 7
    0: 1, 0, 1
    1: 1, 1, 0
    
    To generate 8
    0: 1, 1, 0
    1: 1, 1, 1, 0
    
    To generate 9
    0: 1, 1, 1
    1: 1, 1, 1, 1
    

    另一个简单的答案是生成一个足够大的二进制数,使得mod N不会(统计上)偏向某些数字而不是其他数字。但我认为你不会喜欢这个答案,因为从你的评论判断到另一个答案,你似乎在考虑生成的比特数的效率。

    简而言之,我不确定为什么我对这个答案进行了低估,因为与它使用的位数(〜log(N))相比,这个算法似乎提供了一个很好的分布。

答案 4 :(得分:-1)

  1. 计算N所需的位数(=值为1的最高位的位置) - 让我们称之为k
  2. 从输入的位流中取出第一个k位 - 让我们将其称为X
  3. Result = X mod N
  4. 传播到下一组k位,并从步骤2开始重复生成下一个随机数。
  5. 或者,为了更好地分发,可以应用此步骤而不是步骤3:

    • 比率= N / 2 k
    • 结果= X *比率