Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中将位转换为字节_Python_Python 3.x_Optimization_Bit Manipulation - Fatal编程技术网

在Python中将位转换为字节

在Python中将位转换为字节,python,python-3.x,optimization,bit-manipulation,Python,Python 3.x,Optimization,Bit Manipulation,在Python3.x中,我试图将位字符串转换为字节字符串。在每个字节中,位从高阶填充到低阶。如有必要,最后一个字节用零填充。位字符串最初存储为布尔或整数(0或1)的“集合”,我想返回0-255范围内整数的“集合”。所谓集合,我指的是一个列表或类似的对象,但不是字符串:例如,下面的函数返回一个生成器 到目前为止,我能得到的最快的结果如下: def bitsToBytes(a): s = i = 0 for x in a: s += s + x i +

在Python3.x中,我试图将位字符串转换为字节字符串。在每个字节中,位从高阶填充到低阶。如有必要,最后一个字节用零填充。位字符串最初存储为布尔或整数(0或1)的“集合”,我想返回0-255范围内整数的“集合”。所谓集合,我指的是一个列表或类似的对象,但不是字符串:例如,下面的函数返回一个生成器

到目前为止,我能得到的最快的结果如下:

def bitsToBytes(a):
    s = i = 0
    for x in a:
        s += s + x
        i += 1
        if i == 8:
            yield s
            s = i = 0
    if i > 0:
        yield s << (8 - i)

这里我用列表来展示示例。发电机可以。但是,字符串不会,因此有必要在类似列表的数据和字符串之间来回转换。

在8-er块中使用位并忽略异常的最简单策略:

def getbytes(bits):
    done = False
    while not done:
        byte = 0
        for _ in range(0, 8):
            try:
                bit = next(bits)
            except StopIteration:
                bit = 0
                done = True
            byte = (byte << 1) | bit
        yield byte

getbytes
是一个生成器,它接受一个生成器,也就是说,它可以很好地处理大型且可能无限的流。

步骤1:添加缓冲区零

步骤2:反转位,因为你的尾数是反转的

步骤3:连接成单个字符串

步骤4:一次将8位保存到数组中

第五步:

第六步:利润

def bitsToBytes(a):
    a = [0] * (8 - len(a) % 8) + a # adding in extra 0 values to make a multiple of 8 bits
    s = ''.join(str(x) for x in a)[::-1] # reverses and joins all bits
    returnInts = []
    for i in range(0,len(s),8):
        returnInts.append(int(s[i:i+8],2)) # goes 8 bits at a time to save as ints
    return returnInts
使用:

如果输入是字符串,则专用解决方案可能更快:

>>> bits = '100000001'
>>> padded_bits = bits + '0' * (8 - len(bits) % 8)
>>> padded_bits
'1000000010000000'
>>> list(int(padded_bits, 2).to_bytes(len(padded_bits) // 8, 'big'))
[128, 128]

如果
len(bits)%8==0

@adam,那么最后一个字节是零。如果你是对的,我的意思是list,尽管我认为通常的措辞是“bit string”(可能我错了!)。我更新了问题以澄清这一点。为什么[1,1]输出[192]而不是[3]和[1,0,0,0,0,0,0,0,1]输出[128,128]而不是[1,1]?@CodeMonkey我将字节从高阶位填充到低阶位,并在最后一个字节中添加填充零(因此在低阶位中添加)。因此,一个1单独被理解为字节0b10000000,两个连续的1被理解为字节0b11000000,[1,0,0,0,0,0,1]被理解为字节[0b10000000,0b1000000]。顺便说一下,这与中的位顺序相同。为什么bytestring不是一个可接受的结果?在Python3中,枚举BYTestString(如
b'\x80\x80'
会产生整数,即
bytes
对象是一个字节序列(Python
int
范围(0x100)
中)。为了获得最佳性能,可以在Cython中编写一个C扩展名:
a2b\u-bin():b'1'->b'\x80'
类似于感谢这个非常有趣的“grouper”,以及我不知道的int.to_字节!事实上,你的第一个解决方案在这里稍微慢一点,但你的第二个解决方案比我的解决方案快30%以上,只有一行。您在上面的评论中是对的,返回一个字节字符串是可以的,它们很容易在以后的文件io中使用。使用一个列表作为输入,我这样做
int(“.”join(“01”[x]表示数据中的x)+“0”*k,2).to_字节(n,“big”)
其中k和n的计算与您的示例相同。使用
int(“.”join(map(“01”)。\uu getitem_u,data))+“0”*k,2).to_字节(n,“big”)
@Jean-ClaudeArbaut:你可以发布一个带有时间比较和
''的答案。加入基于
的解决方案。注意:
grouper()
基于的解决方案可以将无限位流转换为无限字节流(只需将
[]
替换为
()
即可将列表转换为生成器)——其目的是接受任意位的“集合”。对于不同类型的输入(位序列、iterable、bytestring)和输入大小(小、大),不同的解决方案可能更快。
def bitsToBytes(a):
    a = [0] * (8 - len(a) % 8) + a # adding in extra 0 values to make a multiple of 8 bits
    s = ''.join(str(x) for x in a)[::-1] # reverses and joins all bits
    returnInts = []
    for i in range(0,len(s),8):
        returnInts.append(int(s[i:i+8],2)) # goes 8 bits at a time to save as ints
    return returnInts
from functools import reduce
from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

bytes = [reduce(lambda byte, bit: byte << 1 | bit, eight_bits)
         for eight_bits in grouper(bits, 8, fillvalue=0)]
[] -> []
[1] -> [128]
[1, 1] -> [192]
[1, 0, 0, 0, 0, 0, 0, 0, 1] -> [128, 128]
>>> bits = '100000001'
>>> padded_bits = bits + '0' * (8 - len(bits) % 8)
>>> padded_bits
'1000000010000000'
>>> list(int(padded_bits, 2).to_bytes(len(padded_bits) // 8, 'big'))
[128, 128]