将二进制位分组
我有一串数字(这里是一个4位数字的例子,但我想用16位整数来做):
L = [0b1000,0b1100,0b1111,0b1001, 0b0000]
我想把所有的第一个位放在一起,然后把所有的第二个位放在一起,再把所有的第三个位放在一起,依此类推,像这样:
out = 0b11110011000010000110
这个解决方案(由@markcial提出)是有效的:
print [[a[i] for a in [format(b,'04b') for b in L]] for i in range(4)]
#[['1', '1', '1', '1', '0'], ['0', '1', '1', '0', '0'], ['0', '0', '1', '0', '0'], ['0', '0', '1', '1', '0']]
但我想避免使用字符串格式化来进行这些二进制操作。
有没有办法在不使用字符串格式化的情况下把位数放在一起?
2 个回答
1
感谢@PauloBu的合作,这里是我想要的结果(我承认我的问题有点不清楚):输出的数字被打包成字节(8位),这样可以方便地写入文件中:
import struct
L = [0b1000,0b1100,0b1111,0b1001, 0b0000]
bits = 4
res = 0
processed_bits = 0
s = ''
for i in range(bits-1,-1,-1):
for x in L:
res = res | (((x&1<<i)>>i) << (7-processed_bits))
processed_bits += 1
if processed_bits == 8:
s += struct.pack('B', res)
res = 0
processed_bits = 0
with open('blah.bin', 'wb') as f:
f.write(s)
1
也许这个算法适合你的需求,我会用4位二进制数字来解释,之后你可以扩展到16位的使用。
L = [0b1000,0b1100,0b1111,0b1001, 0b0000]
bits = 4 # total bits
next_bit = bits*len(L)-1 # next position to be calculated
res = 0
for i in range(bits-1,-1,-1): # iterate 3,2,1,0 (bits backwards)
for x in L: # iterate through every integer in L
res = res | (((x&1<<i)>>i)<<next_bit) # say what? o.O
next_bit-=1 # set next_bit to the next position to be calculated
>>> bin(res)
'0b11110011000010000110'
基本上,这个算法会逐个检查每个数字的每一位,然后对每个数字的特定位进行分析。一旦你知道要分析哪个数字的哪个位置,就会进行一个奇怪的计算:(((x&1<<i)>>i)<<total_bits-1)
。
这个循环会把计算的结果累加到res
中,我来解释一下这个计算:
x&1<<i
会测试第i
位的值是否为1((x&1<<i)>>i)
向后移动i
位,确保结果是1
或0
(((x&1<<i)>>i)<<next_bit)
向前移动next_bit
位,会在next_bit
位置上设置为1
或0
。
你需要这个next_bit
整数来记录结果中下一个需要设置的位。比如说,你有5个4位的数字,你就知道结果会有5*4位。
我不太喜欢这两个for循环。在C语言中这可能还不错,但在Python中效率不是很好。我还在想办法去掉它们。我敢你用这个简单的一行代码来测试它们的性能:
>>>L = [0b1000,0b1100,0b1111,0b1001, 0b0000]
>>>int(''.join(['1' if x&1<<i else '0' for i in range(3,-1,-1) for x in L]),2)
995462
你会对性能感到惊讶。
希望这能帮到你!