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
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
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.
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^
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
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]
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]