寻找一种更优雅的方式将字节转换为位列表
Searching a more elegant way for converting a byte to a list of bits
我目前正在使用这个小函数将一个字节转换为整数位列表,因为我需要迭代一个字节的单个位。
def byteToBitList(byte):
return [int(bit) for bit in "{0:08b}".format(byte)]
不过我觉得不是很优雅。有一个更好的方法吗?可能不使用字符串?
您可以使用以下更快的解决方案:
byte = 0xfc
In [206]: list(map(int, bin(byte)[2:].zfill(8)))
Out[206]: [1, 1, 1, 1, 1, 1, 0, 0]
时间:
In [209]: %timeit byteToBitList(byte)
100000 loops, best of 3: 5.69 us per loop
In [211]: %timeit list(map(int, bin(byte)[2:].zfill(8)))
100000 loops, best of 3: 4.27 us per loop
您总是可以从使用 bitwise operations 中获益,它使用标准整数对象。只需一次将您的数字移动一位并收集最右边的位值。例如:
>>> byte = 0xFC
>>> list_size = 8
>>> [(byte >> i) & 1 for i in range(list_size)][::-1] # reverse this array, since left-most bits are evaluated first.
[1, 1, 1, 1, 1, 1, 0, 0]
时间使用IPython:1000000 loops, best of 3: 1.54 µs per loop
甚至可以在不反转数组的情况下生成此列表:
>>> byte = 0xFC
>>> list_size = 8
>>> [(byte & (1 << (list_size - 1 - k))) >> (list_size - 1 - k) for k in range(list_size)]
[1, 1, 1, 1, 1, 1, 0, 0]
计时使用 IPython:100000 loops, best of 3: 2.3 µs per loop
。显然,反转列表比使用两个班次更快!
此外,this Stack Overflow thread 包含一个非常相似的问题。
如果要避免字符串操作,可以使用二进制操作,即移位<<
和>>
结合逻辑与&
.
>>> def byteToBitList(byte):
return [(byte & (1 << k)) >> k for k in range(8)]
>>> byteToBitList(0xfc)
[0, 0, 1, 1, 1, 1, 1, 1]
您可以将 bin()
与 str.zfill()
结合使用,将整数转换为二进制表示形式:
def byteToBitList(byte):
return [int(bit) for bit in bin(byte)[2:].zfill(8)]
这里假定 byte
确实是一个 0-255 的无符号整数。任何更大的结果列表将超过 8 位,尽管结果是正确的,只是没有填充零。
我目前正在使用这个小函数将一个字节转换为整数位列表,因为我需要迭代一个字节的单个位。
def byteToBitList(byte):
return [int(bit) for bit in "{0:08b}".format(byte)]
不过我觉得不是很优雅。有一个更好的方法吗?可能不使用字符串?
您可以使用以下更快的解决方案:
byte = 0xfc
In [206]: list(map(int, bin(byte)[2:].zfill(8)))
Out[206]: [1, 1, 1, 1, 1, 1, 0, 0]
时间:
In [209]: %timeit byteToBitList(byte)
100000 loops, best of 3: 5.69 us per loop
In [211]: %timeit list(map(int, bin(byte)[2:].zfill(8)))
100000 loops, best of 3: 4.27 us per loop
您总是可以从使用 bitwise operations 中获益,它使用标准整数对象。只需一次将您的数字移动一位并收集最右边的位值。例如:
>>> byte = 0xFC
>>> list_size = 8
>>> [(byte >> i) & 1 for i in range(list_size)][::-1] # reverse this array, since left-most bits are evaluated first.
[1, 1, 1, 1, 1, 1, 0, 0]
时间使用IPython:1000000 loops, best of 3: 1.54 µs per loop
甚至可以在不反转数组的情况下生成此列表:
>>> byte = 0xFC
>>> list_size = 8
>>> [(byte & (1 << (list_size - 1 - k))) >> (list_size - 1 - k) for k in range(list_size)]
[1, 1, 1, 1, 1, 1, 0, 0]
计时使用 IPython:100000 loops, best of 3: 2.3 µs per loop
。显然,反转列表比使用两个班次更快!
此外,this Stack Overflow thread 包含一个非常相似的问题。
如果要避免字符串操作,可以使用二进制操作,即移位<<
和>>
结合逻辑与&
.
>>> def byteToBitList(byte):
return [(byte & (1 << k)) >> k for k in range(8)]
>>> byteToBitList(0xfc)
[0, 0, 1, 1, 1, 1, 1, 1]
您可以将 bin()
与 str.zfill()
结合使用,将整数转换为二进制表示形式:
def byteToBitList(byte):
return [int(bit) for bit in bin(byte)[2:].zfill(8)]
这里假定 byte
确实是一个 0-255 的无符号整数。任何更大的结果列表将超过 8 位,尽管结果是正确的,只是没有填充零。