In python, I have been given a 64 bit integer. This Integer was created by taking several different 8 bit integers and mashing them together into one giant 64 bit integer. It is my job to separate them again.
For example:
Source number: 2592701575664680400
Binary (64 bits): 0010001111111011001000000101100010101010000101101011111000000000
int 1: 00100011 (35)
int 2: 11111011 (251)
int 3: 00100000 (32)
int 4: 01011000 (88)
int 5: 10101010 (170)
int 6: 00010110 (22)
int 7: 10111110 (190)
int 8: 00000000 (0)
So what I would like to do is take my source number 2592701575664680373
and return an array of length 8, where each int in the array are the ints listed above.
I was going to use struct
, but to be perfectly honest, reading the documentation hasn't made it quite clear exactly how I would accomplish that.
Solution without converting the number to a string:
x = 0b0010001111111011001000000101100010101010000101101011111000000000
numbers = list((x >> i) & 0xFF for i in range(0,64,8))
print(numbers) # [0, 190, 22, 170, 88, 32, 251, 35]
print(list(reversed(numbers))) # [35, 251, 32, 88, 170, 22, 190, 0]
Here I used list comprehensions, making a loop in increments of 8 over i
. So i
takes the values 0, 8, 16, 24, 32, 40, 48, 56
.
Every time, the bitshift operator >>
temporarily shifts the number x
down by i
bits. This is equivalent to dividing by 256^i
.
So the resulting number is:
i = 0: 0010001111111011001000000101100010101010000101101011111000000000
i = 8: 00100011111110110010000001011000101010100001011010111110
i = 16: 001000111111101100100000010110001010101000010110
i = 24: 0010001111111011001000000101100010101010
i = 32: 00100011111110110010000001011000
i = 40: 001000111111101100100000
i = 48: 0010001111111011
i = 56: 00100011
By usig & 0xFF
, I select the last 8 bits of this number. Example:
x >> 48: 001000111111101100100000
0xff: 11111111
(x >> 48) & 0xff: 000000000000000000100000
Since the leading zeros do not matter, you have the desired number.
The result is converted to a list and printed in normal and reversed order (like OP wanted it).
I compared the timing of this result to the other solutions proposed in this thread:
In: timeit list(reversed([(x >> i) & 0xFF for i in range(0,64,8)]))
100000 loops, best of 3: 13.9 µs per loop
In: timeit [(x >> (i * 8)) & 0xFF for i in range(7, -1, -1)]
100000 loops, best of 3: 11.1 µs per loop
In: timeit [(x >> i) & 0xFF for i in range(63,-1,-8)]
100000 loops, best of 3: 10.2 µs per loop
In: timeit reversed(struct.unpack('8B', struct.pack('Q', x)))
100000 loops, best of 3: 3.22 µs per loop
In: timeit reversed(struct.pack('Q', x))
100000 loops, best of 3: 2.07 µs per loop
Result: my solution is not the fastest!
Currently, using struct
directly (as proposed by Mark Ransom) seems to be the fastest snippet.