[Tutor] [spoiler] Re: Shifting arrays as though they are a 'word'

Peter Otten __peter__ at web.de
Sat Oct 6 04:10:10 EDT 2018

```Chip Wachob wrote:

> Hello,
>
> 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
> attempted..
>
> 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)
if nbits:
a = 
for bb in b:
hi, lo = divmod(bb << nbits, 256)
a[-1] |= hi
a.append(lo)
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"

```