【问题标题】:How to convert an integer to a list of bits?如何将整数转换为位列表?
【发布时间】:2022-04-13 14:19:11
【问题描述】:

我试图将整数表示为位列表并将其填充为 8 位仅当整数为 :

Example input: 0x15
Desired output: [0, 0, 0, 1, 0, 1, 0, 1]

我是这样做的:

input = 0x15
output = deque([int(i) for i in list(bin(input))[2:]])
while len(output) != 8:
    output.appendleft(0)

我想将任何整数转换为二进制列表。仅当数字需要少于 8 位来表示时才填充为 8。

Another Example input: 0x715
Desired output: [1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]

对于小于 8 位的数字和更大的数字,我如何做到这一点?

【问题讨论】:

    标签: python


    【解决方案1】:

    对于固定大小的 8 位:

    num = 0x15
    out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]
    

    (1 &lt;&lt; (7-n)) 为给定位置创建一个位掩码,然后按位&amp; 测试该位是否在数字中设置。让n 处理 0 到 7 会导致按顺序测试字节中的所有 8 位。

    对于任意大小的数字:

    import math
    num = 0x715
    bits = int(max(8, math.log(num, 2)+1))
    out = [1 if num & (1 << (bits-1-n)) else 0 for n in range(bits)]
    

    【讨论】:

    • 我对此表示赞同,但在编辑后您还需要处理大于 8 位的数字。
    • 对于 little-endian 位列表,您可以使用 [n &amp; 1 &lt;&lt; b and 1 for b in range(bitlength)]
    • 可以进行移位和屏蔽以将所需位带到最右边的位置,从而跳过检查1 if that_bit_over_there_is_one else 0[(num &gt;&gt; shift) &amp; 0x01 for shift in range(7, -1, -1)]
    【解决方案2】:
    >>> [int(n) for n in bin(0x15)[2:].zfill(8)]
    [0, 0, 0, 1, 0, 1, 0, 1]
    

    切片[2:]是去掉0b前缀,zfill(8)是在左边补零。

    【讨论】:

      【解决方案3】:
      number = 0x15
      
      output = [int(x) for x in '{:08b}'.format(number)]
      

      '{:08b}'.format(number)binary 格式表示您的number,0 填充到8 位,然后使用列表推导创建位列表。

      或者,您可以使用map 函数:

      output = map(int, '{:08b}'.format(0x15))
      

      如果你想使用可变位数,这里有一种方法:

      width = 8  # 8bit width
      output = [int(x) for x in '{:0{size}b}'.format(0x15, size=width)]
      output = map(int, '{:0{size}b}'.format(0x15, size=width))
      

      对于 Python 3,使用 list() 包装 map(...) 调用(map 在 Python 2 中返回一个列表,但在 3 中返回一个迭代器)。

      【讨论】:

        【解决方案4】:

        使用格式字符串很容易做到这一点

        >>> "{:08b}".format(0x15)
        '00010101'
        >>> "{:08b}".format(0x151)
        '101010001'
        >>> "{:08b}".format(0x1511)
        '1010100010001'
        

        转换成列表

        >>> [1 if x=='1' else 0 for x in "{:08b}".format(0x15)]
        [0, 0, 0, 1, 0, 1, 0, 1]
        >>> [1 if x=='1' else 0 for x in "{:08b}".format(0x1511)]
        [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
        

        在@Amber 的回答中使用 bit twiddling 可能会更快,但是你必须检查特殊情况并最终得到相当多的代码。如果不需要最高性能,那么在您知道的已经有效的基础上构建会更安全

        【讨论】:

        • 您可以使用list(string) 将字符串转换为列表,因此map(int, list("{:08b}".format(n)) 可以工作
        • @Raniz,但是map 在 Python3 中不返回 list,所以我更喜欢使用列表推导
        • 对,但你可以这样做[int(x) for x in ... ]
        • @RyanHaining,请原谅我过早的优化,但int(x)x=='1' 慢得多
        • @JohnLaRooy .. 感谢您提供有关 map+Py3 的补充信息,并且 int(x) 比 x==1 慢。
        【解决方案5】:

        解决方案

        适用于任意位数,比 accepted answercurrent highest voted answer 更快:

        num = 0xAAAA
        bit_list = [(num >> shift_ind) & 1
                     for shift_ind in range(num.bit_length())] # little endian
        bit_list.reverse() # big endian
        
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
        

        时间

        from timeit import timeit
        
        def accepted_answer(number):
            output = [int(x) for x in '{:08b}'.format(number)]
        
            return output
        
        def highest_voted_answer(num):
            out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]
        
            return out
        
        def this_answer(num):
            bit_list = [(num >> shift_ind) & 1
                        for shift_ind in range(num.bit_length())] # little endian
            bit_list.reverse() # big endian
        
            return bit_list
        
        NUM = 0x15
        ITERATIONS = int(1e7)
        
        print(timeit(lambda: accepted_answer(NUM), number=ITERATIONS))
        print(timeit(lambda: highest_voted_answer(NUM), number=ITERATIONS))
        print(timeit(lambda: this_answer(NUM), number=ITERATIONS))
        
        9.884788331000891
        9.262861715000327
        6.484631327999523
        

        【讨论】:

          【解决方案6】:
          np.unpackbits(np.frombuffer(number, np.dtype('B')))
          

          【讨论】:

          • 有人能查一下这个时间吗?
          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
          【解决方案7】:

          您可以将数字 x 向右移动,然后按位和结果为 1 以获取位置 x 的位,使用 list-comprehension 执行此操作,您将获得您的列表。如果您需要支持负数,我们可能需要在列表中添加前导零,以确保正数不以 1 开头:

          import math
          
          def bits(n):
              # The number of bits we need to represent the number
              num_bits = max(8, int(math.log(abs(n), 2)) + 1)
              # The bit representation of the number
              bits = [ (n >> i) & 1 for i in range(num_bits) ]
              bits.reverse()
              # Do we need a leading zero?
              if n < 0 or bits[0] == 0:
                  return bits
              return [0] + bits
          
          # Examples
          for n in (-0x15, 0x15, 128, 255, 256, -256):
              print("{: 4} = {}".format(n, bits(n)))
          
           -21 = [1, 1, 1, 0, 1, 0, 1, 1]
            21 = [0, 0, 0, 1, 0, 1, 0, 1]
           128 = [0, 1, 0, 0, 0, 0, 0, 0, 0]
           255 = [0, 1, 1, 1, 1, 1, 1, 1, 1]
           256 = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
          -256 = [1, 0, 0, 0, 0, 0, 0, 0, 0]
          

          【讨论】:

            【解决方案8】:
            from math import ceil
            input = 0x15
            bin_string = bin(input)[2:]
            binary = map(int,bin_string.zfill(int(ceil(len(bin_string)/8.0)*8)))
            print(binary)
            

            这将四舍五入到最接近的 8 倍数,如果您只想在 zfill

            0x15 的输出:

            [0, 0, 0, 1, 0, 1, 0, 1]
            

            0x715 的输出:

            [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
            

            如果您只想在小于 128 时添加零,请使用:

            input = 0x715
            bin_string = bin(input)[2:]
            num_bits = (8 if input < 128 else 0)
            binary = map(int,bin_string.zfill(num_bits))
            print(binary)
            

            0x15 的输出:

            [0, 0, 0, 1, 0, 1, 0, 1]
            

            0x715 的输出:

            [1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
            

            【讨论】:

              【解决方案9】:

              我使用位掩码的次数比以前少得多,但是当我使用它们时,我经常需要将一个值分解成各个部分

              def get_Bits(number):
              i = 1
              list_of_hex = []
              while (i <= number):
                  if ((number & i) > 0):
                      bitRepresentation = hex(i)
                      list_of_hex.append(bitRepresentation)
                      
                  i = i*2
              
              return list_of_hex
              

              如果需要二进制分解,可以将(hex)函数改为(bin)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-12-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-08-15
                • 1970-01-01
                相关资源
                最近更新 更多