Integer in a bit field as a list

I created a method for converting int to a bit field (in a list), and it works, but I'm sure there is a more elegant solution - I just looked at it for a long time.

I am curious how would you convert an int to a bitfield represented in list ?

 def get(self): results = [] results.append(1 if (self.bits & 1) else 0) results.append(1 if (self.bits & 2) else 0) results.append(1 if (self.bits & 4) else 0) results.append(1 if (self.bits & 8) else 0) results.append(1 if (self.bits & 16) else 0) results.append(1 if (self.bits & 32) else 0) results.append(1 if (self.bits & 64) else 0) results.append(1 if (self.bits & 128) else 0) return results def set(self, pin, direction): pin -= 1 if pin not in range(0, 8): raise ValueError if direction: self.bits |= (2 ** pin) else: self.bits &=~(2 ** pin) 
+8
python list bit-fields
source share
4 answers

How about this:

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

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

EDIT:

Converting to int using int() is a bit overloaded here. This is much faster:

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

See 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 
+22
source share

This does not use bin :

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

and so you can process any integer as follows:

  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 match lsb int, reorder the ranges, 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 are trying to represent binary values ​​of a fixed length. It returns the minimum number of bits to represent n.

+16
source share

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, although as you can see, you get a list of strings

+4
source share

I do this for my program, where you specify a template to get values ​​from 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 related to your bit sizes:

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

or you can specify the bit size of each value needed with the lines: (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
source share

All Articles