生成大量唯一的随机浮点数(float32)

7
我需要生成一个仅包含唯一单精度随机数的二进制文件。 目的是计算该文件的熵,并将其与其他数据集熵一起使用,计算熵文件/熵_randUnique比率。该值称为“随机性”。 我可以在Python中使用双精度数字并将它们插入set(),使用struct.pack来实现:
    numbers = set()
    while len(numbers) < size:
        numbers.add(struct.pack(precision,random.random()))
    for num in numbers:
        file.write(num)

但是当我改变到单精度时,我不能仅仅更改打包方法(这将产生很多相同的数字,而且循环永远不会结束),也不能使用random生成单精度数。我研究了一下numpy,但据我所知,生成器的工作方式是一样的。如何在二进制文件中获得370914252个唯一的float32,即使它们不是随机的,我认为一个洗牌的序列就足够了。
1个回答

3

您最好的选择是生成随机的32位整数,然后将它们转换为浮点数。在生成这些数字时,您需要拒绝表示无穷大和NAN的位表示。

您可以从整数值生成您的set而不是浮点数值,然后在输出时进行转换。您可以使用位图来检测已经使用过的整数值,而不是使用一个集合; 这更可能适合内存,特别是考虑到您所指示的最大样本大小。

def random_unique_floats(n):
    used = bytearray(0 for i in xrange(2**32 // 8))
    count = 0
    while count < n:
        bits = random.getrandbits(32)
        value = struct.unpack('f', struct.pack('I', bits))[0]
        if not math.isinf(value) and not math.isnan(value):
            index = bits // 8
            mask = 0x01 << (bits & 0x07)
            if used[index] & mask == 0:
                yield value
                used[index] |= mask
                count += 1

for num in random_unique_floats(size):
    file.write(struct.pack('f', num))

请注意,随着样本数量逐渐接近可能的浮点数值数量,运行时间会呈指数级增长。

我从未使用过 yield,我正在尝试使用 for num in random_unique_floats(size): file.write(num),但我不确定它是否正确。它会出现错误 "used = bytearray(0 for i in range(2**32 / 8)) TypeError: 'float' object cannot be interpreted as an integer"。编辑:我已将 xrange 更改为 range,因为我正在使用 Python3。 - SamGamgee
@SamGamgee,那么您需要使用2**32 // 8进行整数除法。我会编辑答案。不过我会保留xrange,这样答案仍然适用于Python 2。 - Mark Ransom
好的,那很有道理(还要感谢您教我//除法:))。我现在正在运行程序,并增加样本,到目前为止,它似乎正常工作!很快会标记为答案。 - SamGamgee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接