【问题标题】:Convert binary to list of digits Python将二进制转换为数字列表 Python
【发布时间】:2012-10-16 08:59:27
【问题描述】:

我有以下场景:

x = 0b0111

我想将此值转换为:

y = [0, 1, 1, 1]

当我转换x = 0b1001 时,我可以得到y = [1, 0, 0, 1],但是当我尝试对x = 0b0111 做同样的事情,然后用str(bin(y)) 转换回来时 - 我似乎失去了领先的0,并且获取0b111

有什么建议吗?

【问题讨论】:

  • 0b0111 == 0b111 那么有什么问题呢?如果您需要固定长度的列表,那么只需在开头添加适当数量的 0。

标签: python list binary


【解决方案1】:

一旦得到字符串0b111,就可以直接拆分出您感兴趣的数字。对于字符串中0b 之后的所有字符,将其转换为整数。

[int(d) for d in str(bin(x))[2:]]

【讨论】:

  • bin(x)返回的对象是类型的,我想我们不需要显式转换它再次到 str() 这应该工作: [int(d) for d in bin(x)[2:]]
【解决方案2】:

就其价值而言,纯算术解决方案似乎略快:

import timeit

def bits1(n):
    b = []
    while n:
        b = [n & 1] + b
        n >>= 1
    return b or [0]

timeit.timeit(lambda: bits1(12345678))
[out] 7.717339038848877

def bits2(n):
    return [int(x) for x in bin(n)[2:]]


timeit.timeit(lambda: bits2(12345678))
[out] 10.297518014907837

2019 年更新:在 python 3.7.3 中,第二个版本稍快。

【讨论】:

  • 对于python 3,您应该将listmap内部移动到map外部。您还可以通过使用b.append(n&1) 而不是b = [n & 1] + b 来赢得一些性能。不幸的是(?)在我的情况下,bits2 选项比纯版本快 10 倍。
  • @ThomasAhle:谢谢,bits2 版本已编辑。在 py3 中它稍微快一些,但没有 10 倍那么快。
【解决方案3】:

先把数字转成二进制,再转成字符串:

str(bin(7))
'0b111' #note the 0b in front of the binary number

接下来,从字符串中删除0b

str(bin(7))[2:]
'111'

最后,我们使用列表推导从字符串中创建一个整数列表,它大致具有以下形式:

[expr for i in iterable]
[int(i) for i in str(bin(x))[2:]]

【讨论】:

    【解决方案4】:

    map(int, list(bin((1<<8)+x))[-4:]) 这样的表达式会给你一个数字的低4位,作为一个列表。 (编辑:更简洁的形式是map(int,bin(x)[2:].zfill(4));见下文。)如果您知道要显示多少位,请将 4([-4:])替换为那个号码;如有必要,将 8((1<<8))设为更大的数字。例如:

    >>> x=0b0111
    >>> map(int,list(bin((1<<8)+x))[-4:])
    [0, 1, 1, 1]
    >>> x=37; map(int,list(bin((1<<8)+x))[-7:])
    [0, 1, 0, 0, 1, 0, 1]
    >>> [int(d) for d in bin((1<<8)+x)[-7:]]
    [0, 1, 0, 0, 1, 0, 1]
    

    上面的最后一个示例显示了使用 map 和 list 的替代方法。以下示例显示了一种用于获取前导零的更简洁的形式。在这些形式中,用所需的最小位数代替 8。

    >>> x=37; [int(d) for d in bin(x)[2:].zfill(8)]
    [0, 0, 1, 0, 0, 1, 0, 1]
    >>> x=37; map(int,bin(x)[2:].zfill(8))
    [0, 0, 1, 0, 0, 1, 0, 1]
    >>> x=37; map(int,bin(x)[2:].zfill(5))
    [1, 0, 0, 1, 0, 1]
    >>> x=37; map(lambda k:(x>>-k)&1, range(-7,1))
    [0, 0, 1, 0, 0, 1, 0, 1]
    

    【讨论】:

      【解决方案5】:

      如果位的长度固定为4,有两种解决方案:

      [int(i) for i in '{0:04b}'.format(0b0111)]
      

      或使用 NumPy,

      import numpy as np
      [int(i) for i in np.binary_repr(0b0111, 4)]
      

      【讨论】:

        【解决方案6】:

        为 f-String 更新:

        x = 0b0111
        y = [int(i) for i in f'{x:04b}']
        

        y = [0, 1, 1, 1]

        或:

        x = 0b0111 # binary representation of int 7
        n_bits = 4 # desired bits' len
        y = [int(i) for i in f'{x:0{n_bits}b}']
        

        将填充一个包含前导 0 的最小 len n 位的列表

        【讨论】:

          【解决方案7】:

          检查这个简单的方法来做到这一点......对于这个特定的场景

          In [41]: x=0b0111
          
          In [42]: l = [0,0,0,0]
          
          In [43]: counter = -1
          
          In [44]: for i in str(bin(x))[2:]:
             ....:     l[counter] = i
             ....:     counter = counter -1
             ....:
          
          In [45]: l
          Out[45]: [0, '1', '1', '1']
          

          【讨论】:

            【解决方案8】:
            c=[]
            for i in bin(7)[2:]: 
                    c.append(int(i)) #turning string "111", to 111
            if len(c)==3:
                c.insert(0,0)
            print(c)
            
            # binary digit 7 produces '0b111' by this slicing[2:], result get '111'
            

            所以如果列表 c 中的元素为 3,则首先插入 0。

            【讨论】:

            • 也请发表一些对答案的解释。
            【解决方案9】:

            不是很python,但是:

            byte = 0b00011001
            arr = []
            for i in range(7, -1, -1):
                arr.append((byte & 1<<i)>>i)
            print(arr)
            
            [0, 0, 0, 1, 1, 0, 0, 1]
            

            这使用位掩码来“提取”每个位并附加到数组中。

            【讨论】:

              【解决方案10】:

              给定一个数字value 和在width 中表示它的位数:

              string = format(value, '0{}b'.format(width))
              binary_list = [0 if c == '0' else 1 for c in string]
              

              这比binary_list = [int(c) for c in string]快三分之一左右

              【讨论】:

                【解决方案11】:

                这是一个不需要字符串解析的简单联机:

                [x >> bin_idx & 1 for bin_idx in reversed(range(x.bit_length()))]
                

                我相信它比这里发布的其他答案要快一些。

                【讨论】:

                  猜你喜欢
                  • 2020-06-20
                  • 1970-01-01
                  • 2010-11-22
                  • 2021-01-31
                  • 2021-07-12
                  • 2014-11-07
                  • 2019-08-12
                  • 2014-03-03
                  • 2019-04-02
                  相关资源
                  最近更新 更多