我有一个数字列表(这里有一个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']]
但我想避免字符串格式化来执行这些二进制操作。
如何在不使用字符串格式的情况下将位组合在一起?
答案 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)
计算结果上,我解释:
res
将测试位置x&1<<i
上的位是否亮起i
向后移((x&1<<i)>>i)
位将确保结果为i
或1
0
向前移动(((x&1<<i)>>i)<<next_bit)
会将位置设为next_bit
或1
位置0
。您需要此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)