[Tutor] [spoiler] Re: Shifting arrays as though they are a 'word'
__peter__ at web.de
Sat Oct 6 04:10:10 EDT 2018
Chip Wachob wrote:
> I was not able to find any answers in the archive on this one.
> I'm wondering if this task can be done in a better way than what I've
> I have an array of bytes. Up to 64, which makes for 512 bits.
> I am reading these bytes in serially, and once I have a collection of
> them, I want to shift them by 'n' bits. The size of the array and the
> number of bits are both variable up to the limit of 64/512.
> Now, I've played around with looping through the bytes and taking the
> LSByte and shifting it by 'n' bits using >> or << and that works for
> the first byte. But then I need to take the next byte in the sequence
> and shift it in the opposite direction by 8-n bits using << or >>
> (opposite the LSByte direction), respectively. Then I OR the two
> bytes and save them into the location of the LSByte and then move to
> the next byte in the sequence and so on. While this works most of the
> time, I sometimes get strange behavior at the 'fringes' of the bytes.
> Sometimes I end up with zero, or the shift seems to 'roll over'.
> I'm thinking that maybe there's a way to treat the array / list and
> shift allowing the bits to transfer from byte to byte as needed.
> Maybe by concatenating the bytes into one huge word and then breaking
> it apart again?
> I'm thinking that you folks out there know of a built-in function, or,
> an easier and more predictable way to accomplish the same.
Here are two ways to implement the left shift:
def bitshift(b, n, byteorder="big"):
size = len(b) + (n + 7) // 8
shifted = int.from_bytes(b, byteorder) << n
return shifted.to_bytes(size, byteorder)
def bitshift2(b, n):
nbytes, nbits = divmod(n, 8)
a = 
for bb in b:
hi, lo = divmod(bb << nbits, 256)
a[-1] |= hi
b = bytes(a)
return b + b"\x00" * nbytes
assert bitshift(b"\xaa\xbb", 12) == b"\x0a\xab\xb0\x00"
assert bitshift2(b"\xaa\xbb", 12) == b"\x0a\xab\xb0\x00"
More information about the Tutor