Python整数的位反转

Python整数的位反转,python,python-2.7,bit-manipulation,Python,Python 2.7,Bit Manipulation,给定一个十进制整数(如65),如何在Python中反转底层位?即以下操作: 65 → 01000001 → 10000010 → 130 这项任务似乎可以分为三个步骤: 将十进制整数转换为二进制表示形式 倒位 转换回十进制 第2步和第3步似乎很简单(请参阅和第2步相关的问题),但我仍停留在第1步。步骤#1的问题是用填充零(即65=01000001,而不是1000001)检索完整的十进制表示 我到处找了找,但似乎什么也找不到。没有必要,也没有办法“将十进制整数转换为二进制表示”。所有Python

给定一个十进制整数(如65),如何在Python中反转底层位?即以下操作:

65 → 01000001 → 10000010 → 130
这项任务似乎可以分为三个步骤:

  • 将十进制整数转换为二进制表示形式
  • 倒位
  • 转换回十进制
  • 第2步和第3步似乎很简单(请参阅和第2步相关的问题),但我仍停留在第1步。步骤#1的问题是用填充零(即65=01000001,而不是1000001)检索完整的十进制表示


    我到处找了找,但似乎什么也找不到。

    没有必要,也没有办法“将十进制整数转换为二进制表示”。所有Python整数都表示为二进制;为了方便打印,它们只是转换成十进制

    如果要继续解决反转问题,只需找到合适的
    numbits
    。您可以手动指定,也可以使用(Python 2.7和3.1中的新功能)计算表示整数
    n
    所需的位数

    然而,对于65,这将给你7,因为没有理由65需要更多的位。(您可能希望将其四舍五入到8的最接近倍数…)

    您可以指定任意填充长度来代替8。如果你真的想变得花哨

    b = '{:0{width}b}'.format(n, width=width)
    int(b[::-1], 2)
    

    允许您以编程方式指定宽度。

    如果您想要更高的速度,可以使用中描述的技术

    def反转遮罩(x):
    x=((x&0x5555)>1)
    x=((x&0x33333333)>2)
    x=((x&0x0f0f)>4)
    x=((x&0x00FF00FF)>8)
    x=((x&0x0000FFFF)>16)
    返回x
    
    您可以使用移位和掩码测试数字的第i位。例如,65的第6位是
    (65>>6)&1
    。您可以通过将1向左向右移动几次,以类似的方式设置位。这些洞察为您提供了如下代码(在“n”位的字段中反转x)

    def倒档(x,n):
    结果=0
    对于x范围内的i(n):
    如果(x>>i)&1:结果|=1
    
    对于每个循环,原始数字将删除最右边的位(二进制)。我们得到最正确的位并乘以2(
    另一种方法是循环通过两端的位并相互交换

    i = 0; j = 7
    num = 230
    print(bin(num))
    while i<j:
        # Get the bits from both end iteratively
        if (x>>i)&1 != (x>>j)&1:
            # if the bits don't match swap them by creating a bit mask
            # and XOR it with the number 
            mask = (1<<i) | (1<<j)
            num ^= mask
        i += 1; j -= 1
    print(bin(num))
    
    i=0;j=7
    num=230
    打印(仓位(数量))
    而我>我)&1!=(x>>j)和1:
    #如果位不匹配,则通过创建位掩码来交换它们
    #然后用数字XOR它
    
    掩码=(1最好的方法是执行逐位移位

    def reverse_Bits(n, no_of_bits):
        result = 0
        for i in range(no_of_bits):
            result <<= 1
            result |= n & 1
            n >>= 1
        return result
    # for example we reverse 12 i.e 1100 which is 4 bits long
    print(reverse_Bits(12,4))
    
    def反向位(n,无位):
    结果=0
    对于范围内的i(无位):
    结果=1
    返回结果
    #例如,我们反转4位长的12即1100
    打印(反向_位(12,4))
    
    需要定期对数字数组应用此操作,而不是对单个数字应用此操作。 为了提高速度,最好使用NumPy数组。 有两种解决办法

    x1.34比第二种溶液快:

    import numpy as np
    def reverse_bits_faster(x):
      x = np.array(x)
      bits_num = x.dtype.itemsize * 8
      # because bitwise operations may change number of bits in numbers
      one_array = np.array([1], x.dtype)
      # switch bits in-place
      for i in range(int(bits_num / 2)):
        right_bit_mask = (one_array << i)[0]
        left_bit = (x & right_bit_mask) << (bits_num - 1 - i * 2)
        left_bit_mask = (one_array << (bits_num - 1 - i))[0]
        right_bit = (x & left_bit_mask) >> (bits_num - 1 - i * 2)
        moved_bits_mask = left_bit_mask | right_bit_mask
        x = x & (~moved_bits_mask) | left_bit | right_bit
      return x
    
    将numpy导入为np
    def反转位快(x):
    x=np.数组(x)
    bits_num=x.dtype.itemsize*8
    #因为按位操作可能会改变数字中的位数
    一个数组=np.array([1],x.dtype)
    #将位切换到位
    对于范围内的i(int(bit_num/2)):
    右\u位\u掩码=(一个\u数组=1
    返回x_反转
    
    一种低效但简洁的方法,适用于Python 2.7和Python 3:

    def bit_reverse(i, n):
        return int(format(i, '0%db' % n)[::-1], 2)
    
    例如:

    >>> bit_reverse(65, 8)
    130
    

    您还可以使用查找表(可以使用上述方法一次生成):


    对于第一步,您可以使用
    str(bin(65))[2:].zfill(8)
    。现在懒得/懒得进一步研究这个问题。但是您可能应该按照larsmans说的去做。这不太正确,因为您可以得到一个表示位的字符串(
    bin(n)
    ,或者
    '{:b}'。格式(n)
    。另外,您可以使用
    .bit\u长度()
    查找表示一个数字所需的确切位数。@nneonneo:我假设OP希望处理整数本身,而不是字符串表示,因为有链接。但是感谢
    bit_length
    方法,我不知道这一点。优雅而简洁。我需要将格式字符串更改为
    '{:08b}“
    按规定工作。啊,是的,他想要填充零。我会修改。如果我做
    int({:b})。格式(65)[:-1],2)
    ,我只得到
    65
    作为输出。使用
    {:08b}
    而不是
    {:b}”
    给出了正确的结果,因此+1是一个优雅的解决方案。是的,抱歉。轻微的阅读理解失败,答案修改。这是列表切片,导致以相反的顺序迭代列表。您必须考虑要反转的位数。例如,您希望反转一个字节中的位。您希望0x1将被转换与0x80(0b00000001->0b10000000)相关。在当前的实现中,您仍然会在输出上得到0x1。fyi:链接现在已断开。此函数是否仅限于INT,还是将在bignum类型的数字上工作?由于链接断开,可以在此处找到相同的过程,并提供更多信息:
    i = 0; j = 7
    num = 230
    print(bin(num))
    while i<j:
        # Get the bits from both end iteratively
        if (x>>i)&1 != (x>>j)&1:
            # if the bits don't match swap them by creating a bit mask
            # and XOR it with the number 
            mask = (1<<i) | (1<<j)
            num ^= mask
        i += 1; j -= 1
    print(bin(num))
    
    def reverse_Bits(n, no_of_bits):
        result = 0
        for i in range(no_of_bits):
            result <<= 1
            result |= n & 1
            n >>= 1
        return result
    # for example we reverse 12 i.e 1100 which is 4 bits long
    print(reverse_Bits(12,4))
    
    import numpy as np
    def reverse_bits_faster(x):
      x = np.array(x)
      bits_num = x.dtype.itemsize * 8
      # because bitwise operations may change number of bits in numbers
      one_array = np.array([1], x.dtype)
      # switch bits in-place
      for i in range(int(bits_num / 2)):
        right_bit_mask = (one_array << i)[0]
        left_bit = (x & right_bit_mask) << (bits_num - 1 - i * 2)
        left_bit_mask = (one_array << (bits_num - 1 - i))[0]
        right_bit = (x & left_bit_mask) >> (bits_num - 1 - i * 2)
        moved_bits_mask = left_bit_mask | right_bit_mask
        x = x & (~moved_bits_mask) | left_bit | right_bit
      return x
    
    import numpy as np
    def reverse_bits(x):
      x = np.array(x)
      bits_num = x.dtype.itemsize * 8
      x_reversed = np.zeros_like(x)
      for i in range(bits_num):
        x_reversed = (x_reversed << 1) | x & 1
        x >>= 1
      return x_reversed
    
    def bit_reverse(i, n):
        return int(format(i, '0%db' % n)[::-1], 2)
    
    >>> bit_reverse(65, 8)
    130
    
    LUT = [0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
           8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120,
           248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180,
           116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60,
           188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50,
           178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218,
           58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214,
           54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94,
           222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81,
           209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89,
           217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85,
           213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157,
           93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147,
           83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27,
           155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23,
           151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239,
           31, 159, 95, 223, 63, 191, 127, 255]
    
    def reverseBitOrder(uint8):
        return LUT[uint8]