Convert a 64 bit integer into 8 separate 1 byte integers in python

后端 未结 5 1330
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-20 12:20

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.

5条回答
  •  轮回少年
    2020-12-20 13:08

    Solution

    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]
    

    Explanation

    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).

    Performance

    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.

提交回复
热议问题