17

我创建了一种将 an 转换int为位域(在列表中)的方法并且它可以工作,但我确信有更优雅的解决方案 - 我已经盯着它很久了。

我很好奇,您如何将 a 转换int为 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)
4

6 回答 6

37

这个怎么样:

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
于 2012-04-25T18:54:57.060 回答
27

这不使用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 的最小位数。

于 2012-04-25T19:02:52.113 回答
4

尝试

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

这对负 n 不起作用,如您所见,为您提供了一个字符串列表

于 2012-04-25T19:01:13.947 回答
1

不适用于负值

>>> import numpy as np
>>> [int(x) for x in np.binary_repr(123)]
[1, 1, 1, 1, 0, 1, 1]
于 2018-11-29T17:03:54.770 回答
1

固定长度的数组

固定长度的数组:

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

你相信字符串也是一个数组吗?不?看:

>>> [int(x) for x in '{0:07b}'.format(12)]
[0, 0, 0, 1, 1, 0, 0]
于 2020-11-25T06:54:20.187 回答
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 友好)

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:更快的代码^

于 2015-05-26T04:40:19.797 回答