Integer to bitfield as a list

前端 未结 6 730
一向
一向 2021-02-13 01:33

I\'ve created a method to convert an int to a bitfield (in a list) and it works, but I\'m sure there is more elegant solution- I\'ve just been staring at it for to

相关标签:
6条回答
  • 2021-02-13 02:00

    Try

    >>>n=1794
    >>>bitfield=list(bin(n))[2:]
    >>>bitfield
    ['1', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0']
    

    This does not work for negative n though and as you see gives you a list of strings

    0 讨论(0)
  • 2021-02-13 02:10

    This doesn't use bin:

     b = [n >> i & 1 for i in range(7,-1,-1)]
    

    and this is how to handle any integer this way:

     b = [n >> i & 1 for i in range(n.bit_length() - 1,-1,-1)]
    

    See bit_length.

    If you want index 0 of the list to correspond to the lsb of the int, change the range order, i.e.

    b = [n >> i & 1 for i in range(0, n.bit_length()-1)]
    

    Note also that using n.bit_length() can be a point of failure if you're trying to represent fixed length binary values. It returns the minimum number of bits to represent n.

    0 讨论(0)
  • 2021-02-13 02:15

    I'm doing this for my program where you specify a template to get your values from an int:

    def field(template, value):
        sums = [int(v) if v.__class__==str else len(bin(v))-2 for v in template]
        return [(value>> (sum(sums[:i]) if i else 0) )&(~(~0<<int(t)) if t.__class__==str else t) for i,t in enumerate(template)]
    

    how to use
    in the template, specify ints relating to your bit-sizes:

    field([0b1,0b111,0b1111], 204) #>>> [0, 6, 12]
    

    or you can specify the bit-size of each value needed using strings: (noob friendly)

    field(['1','3','4'], 204) #>>> [0, 6, 12]
    

    EDIT: and vice versa: (separate code)

    field(['1','3','4'], [0, 6, 12]) #>>> 204
    field([0b1,0b111,0b1111], [0,3,9]) #>>> 150
    

    the code:

    def field(template, value):
        res = 0
        for t, v in zip(template, value)[::-1]: res = (res << (t.bit_length() if t.__class__ is int else int(t)) )|v
        return res
    

    EDIT2: faster code^

    0 讨论(0)
  • 2021-02-13 02:20

    How about this:

    def bitfield(n):
        return [int(digit) for digit in bin(n)[2:]] # [2:] to chop off the "0b" part 
    

    This gives you

    >>> bitfield(123)
    [1, 1, 1, 1, 0, 1, 1]
    >>> bitfield(255)
    [1, 1, 1, 1, 1, 1, 1, 1]
    >>> bitfield(1234567)
    [1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1]
    

    This only works for positive integers, though.

    EDIT:

    Conversion to int using int() is a bit overkill here. This is a lot faster:

    def bitfield(n):
        return [1 if digit=='1' else 0 for digit in bin(n)[2:]]
    

    See the timings:

    >>> import timeit
    >>> timeit.timeit("[int(digit) for digit in bin(123)[2:]]")
    7.895014818543946
    >>> timeit.timeit("[123 >> i & 1 for i in range(7,-1,-1)]")
    2.966295244250407
    >>> timeit.timeit("[1 if digit=='1' else 0 for digit in bin(123)[2:]]")
    1.7918431924733795
    
    0 讨论(0)
  • 2021-02-13 02:22

    Array with fixed length

    Array with fixed length:

    >>> '{0:07b}'.format(12)
    '0001100'
    

    Do you believe string is also an array? No? See:

    >>> [int(x) for x in '{0:07b}'.format(12)]
    [0, 0, 0, 1, 1, 0, 0]
    
    0 讨论(0)
  • 2021-02-13 02:24

    Does not work for negative values

    >>> import numpy as np
    >>> [int(x) for x in np.binary_repr(123)]
    [1, 1, 1, 1, 0, 1, 1]
    
    0 讨论(0)
提交回复
热议问题