我需要确定性地生成一个随机列表,其中包含从 0 到 2^32-1 的数字。
这将是一种天真的(并且完全没有功能)的做法,只是为了清楚我想要什么。
import random
numbers = range(2**32)
random.seed(0)
random.shuffle(numbers)
我已经尝试使用 numpy.arange() 制作列表并使用 pycrypto 的 random.shuffle() 对其进行洗牌。制作列表消耗了大约 8gb 的 ram,然后洗牌将其增加到大约 25gb。我只有 32gb 可以提供。但这并不重要,因为...
我已经尝试将列表切割成 1024 片并尝试上面的方法,但即使是这些片中的一个也太长了。我将这些切片中的一个切成 128 个更小的切片, 每个切片花费了大约 620 毫秒。如果它线性增长,那么这意味着整个过程大约需要 22 个半小时才能完成。这听起来不错,但它不是线性增长的。
我尝试过的另一件事是为每个条目生成随机数并将其用作新位置的索引。然后我沿着列表往下看,并尝试将数字放在新索引处。如果该索引已在使用中,则该索引会递增,直到找到空闲索引为止。这在理论上是可行的,它可以完成大约一半的工作,但接近尾声时,它必须不断搜索新的位置,并在列表中循环数次。
有什么办法可以解决这个问题吗?这是一个可行的目标吗?
请您参考如下方法:
计算所有值似乎是不可能的,因为 Crypto 在大约一毫秒内计算一个随机整数,所以整个工作需要几天时间。
这是作为生成器的 Knuth 算法实现:
from Crypto.Random.random import randint
import numpy as np
def onthefly(n):
numbers=np.arange(n,dtype=np.uint32)
for i in range(n):
j=randint(i,n-1)
numbers[i],numbers[j]=numbers[j],numbers[i]
yield numbers[i]
对于 n=10 :
gen=onthefly(10)
print([next(gen) for i in range(9)])
print(next(gen))
#[9, 0, 2, 6, 4, 8, 7, 3, 1]
#5
对于 n=2**32,生成器需要一分钟时间进行初始化,但调用的时间复杂度为 O(1)。
