理解Python中的位操作函数

时间:2014-03-12 16:14:53

标签: python bit-manipulation

我真的需要一些帮助来理解这段代码:据我所知,它是在一个字节的中间插入一个字节数组的值,但是,因为我需要在Javascript中重新实现它,我想完全理解它。

Array = [0] * 256
Bit_Offset = 0

[...]

def AddBits(byte_offset, bit_offset, bits, value):
    global Bit_Offset
    global Array

    for i in range(bits):
        if(value & 0x01):
            Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))] |= (0x01 << ((bit_offset + Bit_Offset + i) % 8));
        value /=2
    Bit_Offset += bits

它的使用方式如下:

AddBits(3, 0, 8, 0xaa)
AddBits(3, 0, 3, 0xbb)

编辑:好吧,它确实在一个字节中的自定义偏移处插入值,但它对我来说看起来像一个非常差的算法(插入每个位的循环,真的吗?)。必须有更好的方法来做到这一点!

我不太擅长二进制数学,但我提出了改变8 - bit_offset之类的值的想法(以便第一位在一个字节中的正确偏移处),然后分裂如果它跨越多个字节并最终将其与数组中的字节进行或运算,则它在部分中。它是否正确?如何实现拆分部分?

1 个答案:

答案 0 :(得分:1)

我将重新介绍位类型操作符。

if(value & 0x01):

检查最低有效位是1还是0.如果是0,我们什么都不做。

Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))]

由于数组中的所有值都是单个字节,因此byte_offset是我们要去的位置的索引。添加到byte_offset的是来自本地位计数器和全局位计数器的位的附加偏移,然后将其转换为除以8的字节。最后,我们得到将要放置该位的字节的索引。

((bit_offset + Bit_Offset + i) % 8)

这是计算我们要进行OR的位位置。

|= (0x01 << 

这需要我们的位置并将1移位到该位置然后将其与已存在的任何位置进行或运算。我们知道我们可以在这里使用1,因为if语句将过滤任何0。

value /=2

这有效地向右移位,将下一位置于LSB中。 (可以替换为value >>=1

Bit_Offset += bits

最后,我们将添加的位添加到全局偏移量中。

它的作用

此函数采用数组(字节数组)和位全局位偏移量,参数位偏移量和参数字节偏移量定义的位位置的值进行逐位或运算。它一次做一次的原因是因为你可能需要设置多个Array索引(试试AddBits(3, 4, 8, 0xaa)并看看我的意思)。

一个改进是将for循环更改为:

for i in range(bits):
    Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))] |= ((value & 1) << ((bit_offset + Bit_Offset + i) % 8));
    value >>=1

编辑: 你也可以一次做一个字节

def AddBits2(byte_offset, bit_offset, bits, value):
    global Bit_Offset
    global Array

    # precompute offsets
    bit_offset += Bit_Offset
    byte_offset += bit_offset / 8
    Bit_Offset += bits

    # Mask out any extra bits in value and adjust value to align to byte
    value = (((1 << bits) - 1) & value) << (bit_offset % 8)

    # go through bytes and OR them in one byte at a time
    for i in range((bits + 7) / 8) :
        Array[byte_offset + i] |= (value & 0xff) 
        value >>=8