将二进制位组合在一起

时间:2014-03-25 09:20:34

标签: python binary bit-manipulation

我有一个数字列表(这里有一个4位数字的例子,但我想用16位整数来做):

L = [0b1000,0b1100,0b1111,0b1001, 0b0000]

我希望将所有第1位组合在一起,然后将所有第2位组合在一起,然后将所有第3位组合在一起,等等,如下所示:

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 个答案:

答案 0 :(得分: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'

基本上,它所做的是遍历每个位置以在每个数字中进行分析,然后遍历每个数字来分析该位置,一旦你知道要分析什么位置的数字,你就执行这个奇怪的计算:{ {1}}。

循环将累积在(((x&1<<i)>>i)<<total_bits-1)计算结果上,我解释:

  1. res将测试位置x&1<<i上的位是否亮起
  2. i向后移((x&1<<i)>>i)位将确保结果为i1
  3. 0向前移动(((x&1<<i)>>i)<<next_bit)会将位置设为next_bit1位置0
  4. 您需要此next_bit整数来记录您需要设置的结果的下一位。例如,由于您有5位四位数,因此您知道结果将具有5 * 4位。

    我不喜欢那两个for循环。在C中这可能是好的,但在Python中它们效率不高。我还在想办法删除它们。我敢用这个简单的oneliner对它们进行基准测试:

    next_bit

    你会对表现感到惊讶。

    希望这有帮助!

答案 1 :(得分: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)
相关问题