问题
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 long.
I'm curious, how would you convert a int
to a bitfield represented in a 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)
回答1:
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
回答2:
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.
回答3:
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
回答4:
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]
回答5:
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^
回答6:
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]
来源:https://stackoverflow.com/questions/10321978/integer-to-bitfield-as-a-list