避免从随机

时间:2017-07-20 20:41:54

标签: python random

我想生成随机数并将它们存储在列表中,如下所示:

alist = [random.randint(0, 2 ** mypower - 1) for _ in range(total)]

我关注的是:我想生成total=40 million范围内的(0, 2 ** mypower - 1)值。如果是mypower = 64,则alist的大小约为20GB(40M * 64 * 8),这对我的笔记本电脑内存来说非常大。我有一个想法,迭代生成一大块值,一次说500万,并将它们保存到一个文件,这样我就不必一次生成所有40M值。我担心的是,如果我在循环中执行此操作,则可以保证random.randint(0, 2 ** mypower - 1)不会生成已从上一次迭代生成的值?像这样:

        for i in range(num_of_chunks):
            alist = [random.randint(0, 2 ** mypower - 1) for _ in range(chunk)]
            # save to file

5 个答案:

答案 0 :(得分:4)

好吧,因为效率/速度并不重要,我认为这会奏效:

s = set()
while len(s) < total:
    s.add(random.randint(0, 2 ** mypower - 1))
alist = list(s)

由于集合中只能包含唯一元素,我认为这样做效果不错

答案 1 :(得分:2)

为了保证唯一值,您应该避免使用random。相反,你应该使用加密。由于加密是可逆的,因此在给定相同密钥的情况下,唯一输入可保证唯一输出加密数字0,1,2,3 ......并且您将获得保证的独特随机看似输出,使您可以使用安全加密。良好的加密旨在提供随机看似的输出。

跟踪关键(必要)以及你有多远。对于您的第一批加密整数0..5,000,000。对于第二批加密5,000,001..10,000,000等等。

您需要64位数字,因此在ECB模式下使用DES。 DES是64位密码,因此每次加密的输出将为64位。 ECB模式确实存在缺陷,但仅适用于相同的输入。您提供的是独特的输入,因此弱点与您的特定应用无关。

如果您需要重新生成相同的数字,只需使用相同的密钥重新加密它们即可。如果您需要一组不同的随机数(将从第一组中复制一些),则使用不同的密钥。唯一性的保证仅适用于固定密钥。

答案 2 :(得分:1)

生成不重复的随机值的一种方法是首先创建一个连续值列表

l = list(range(1000))

然后shuffle

import random
random.shuffle(l)

你可以多次这样做,并将其保存在一个文件中,但是你的范围有限,因为你的内存有限,你永远不会看到整个画面(这就像尝试一样在没有内存的情况下对大型列表进行排序)

正如有人指出的那样,要获得大量的随机数,你需要大量的内存,这么简单但效率不高。

我刚才的另一个黑客:做与上面相同但使用步骤生成一个范围。然后在第二遍中,为值添加随机偏移。即使偏移值重复,也保证永远不会产生两次相同的数字:

import random

step = 10

l = list(range(0,1000-step,step))
random.shuffle(l)
newlist = [x+random.randrange(0,step) for x in l]

具有所需的最大值和迭代次数:

import random

number_of_iterations = 40*10**6
max_number = 2**64
step = max_number//number_of_iterations

l = list(range(0,max_number-step,step))
random.shuffle(l)
newlist = [x+random.randrange(0,step) for x in l]
print(len(newlist),len(set(newlist)))

在我的笔记本电脑上运行1-2分钟,并提供40000000个不同的值(均匀分布在整个范围内)

答案 3 :(得分:0)

通常,随机数生成器根本不是随机数。事实上,这在某些情况下非常有用。如果您希望在第二次迭代后值是唯一的,请向其发送不同的种子值。

random.seed()

相同的种子将生成相同的列表,因此如果您希望下一次迭代相同,请使用相同的种子。如果你想要它不同,请使用不同的种子。

答案 4 :(得分:0)

可能需要高CPU和物理内存! 我建议你对数据进行分类。 例如,您可以保存: 所有以10开头的数字都是5个字符(例如:10365)到10-5.txt

所有以11开头的数字是6个字符(例如:114567)到11-6.txt

然后检查一个新号码: 例如,我的号码是9256547 它以92开头,是7个字符。 所以我搜索92-7.txt这个数字,如果不重复,我会将它添加到92-7.txt 最后,您可以将所有文件连接在一起。 对不起如果我有错误。我的主要语言不是英语。