我已经创建了一个将int
转换为位域(在列表中)的方法,但它确实有效,但我确信有更优雅的解决方案 - 我只是一直在盯着它长。
我很好奇,您如何将int
转换为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)
答案 0 :(得分:29)
这个怎么样:
def bitfield(n):
return [int(digit) for digit in bin(n)[2:]] # [2:] to chop off the "0b" part
这会给你
>>> 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]
但这仅适用于正整数。
修改强>
使用int
转换为int()
在这里有点矫枉过正。这要快得多:
def bitfield(n):
return [1 if digit=='1' else 0 for digit in bin(n)[2:]]
见时间:
>>> 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
答案 1 :(得分:21)
这不使用bin
:
b = [n >> i & 1 for i in range(7,-1,-1)]
这是如何以这种方式处理任何整数:
b = [n >> i & 1 for i in range(n.bit_length() - 1,-1,-1)]
请参阅bit_length
。
如果希望列表的索引0对应于int的lsb,请更改范围顺序,即
b = [n >> i & 1 for i in range(0, n.bit_length()-1)]
另请注意,如果您尝试表示固定长度的二进制值,则使用n.bit_length()可能会失败。它返回表示n的最小位数。
答案 2 :(得分:4)
尝试
>>>n=1794
>>>bitfield=list(bin(n))[2:]
>>>bitfield
['1', '1', '1', '0', '0', '0', '0', '0', '0', '1', '0']
这不适用于否定n,正如您所见,为您提供了一个字符串列表
答案 3 :(得分:0)
我正在为我的程序执行此操作,您可以在其中指定模板以从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)]
如何使用
在模板中,指定与您的位大小相关的整数:
field([0b1,0b111,0b1111], 204) #>>> [0, 6, 12]
或者您可以使用字符串指定所需的每个值的位大小:( noob friendly)
field(['1','3','4'], 204) #>>> [0, 6, 12]
编辑:反之亦然:(单独的代码)
field(['1','3','4'], [0, 6, 12]) #>>> 204
field([0b1,0b111,0b1111], [0,3,9]) #>>> 150
代码:
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:更快的代码^
答案 4 :(得分:0)
不适用于负值
This page isn’t working localhost didn’t send any data.
ERR_EMPTY_RESPONSE
答案 5 :(得分:0)
固定长度的数组:
>>> '{0:07b}'.format(12)
'0001100'
您相信字符串也是数组吗?没有?参见:
>>> [int(x) for x in '{0:07b}'.format(12)]
[0, 0, 0, 1, 1, 0, 0]