将大量数字乘以 random() (Python)

Geo*_*rdt 1 python optimization largenumber

问题:生成大型二进制字符串(长度 2000+)。动作要快,因为该generateRandom()函数将在算法中被调用300,000次。

尝试的解决方案:生成 3 或 4 个二进制数并将它们全部附加在一起 ​​500 次。这太慢了。

对 random.random() 进行一次调用并将其乘以一个巨大的数字。转换为二进制一次即可完成。这适用于较小的数字,但由于二进制字符串必须具有一定的长度,因此要转换为二进制的数字必须非常巨大(2 ** len(binString))。

当前代码(适用于较小的数字):

binaryRepresentation = ''

binaryRepresentation += bin(int(random.random() * (2 ** binLength)))[2:].zfill(binLength)
Run Code Online (Sandbox Code Playgroud)

我需要帮助修复的错误:此调用会抛出一个“长整型太大,无法转换为浮点数”和大量数字。有没有办法使整个算法更高效或使这个大数字可以转换为浮点数?

谢谢你!

jfs*_*jfs 5

衡量它是否足够快以满足您的目的,“随机性”可能会随着您的调用而减少:os.urandom(250)。它产生一个二进制字符串,也称为字节。

为了避免“long int 太大而无法转换为 float”错误,请不要使用浮点数。

如果您需要带有k随机位的整数而不是二进制字符串:

import random
r = random.SystemRandom()

n = r.getrandbits(2000) # uses os.urandom() under the hood
Run Code Online (Sandbox Code Playgroud)

获取由“0”和“1”组成的字符串:

k = 2000
binstr = "{:0{}b}".format(r.getrandbits(k), k)
Run Code Online (Sandbox Code Playgroud)

注意:如果不使用,则不能用于randint/randrange大数字:getrandbits

import random

class R(random.Random):
    def random(self): # override random to suppress getrandbits usage
        return random.random()

r = R()
r.randrange(2**2000) # -> OverflowError: long int too large to convert to float
Run Code Online (Sandbox Code Playgroud)

b2a_bin

b2a_bin()扩展允许直接从字节串创建二进制字符串(“01”),而无需创建中间的 Python 整数。它比纯 Python 类似物快 3-20 倍:

def b2a_bin_bin(data):
    return bin(int.from_bytes(data, 'big', signed=False)
               )[2:].zfill(len(data)*8).encode('ascii', 'strict')

def b2a_bin_format(data):
    n = int.from_bytes(data, 'big', signed=False)
    return "{:0{}b}".format(n, len(data)*8).encode('ascii', 'strict')
Run Code Online (Sandbox Code Playgroud)

用法:

>>> import os
>>> from b2a_bin import b2a_bin
>>> b2a_bin.b2a_bin(b'\x0a')
b'00001010'
>>> b2a_bin(os.urandom(5))
b'1001111011000011111001110010000101111010'
Run Code Online (Sandbox Code Playgroud)