反转Python整数的位

时间:2012-10-01 22:20:36

标签: python python-2.7 bit-manipulation

给定十进制整数(例如65),如何反转Python中的基础位?即。以下操作:

65 → 01000001 → 10000010 → 130

这项任务似乎可以分为三个步骤:

  1. 将十进制整数转换为二进制表示
  2. 反转位
  3. 转换回小数
  4. 步骤#2和3看起来非常简单(参见thisthis所以与步骤#2相关的问题),但我坚持第1步。步骤#1的问题是检索带有填充零的完整十进制表示(即65 = 01000001,而不是1000001)。

    我四处寻找,但似乎找不到任何东西。

10 个答案:

答案 0 :(得分:34)

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

您可以指定任何填充长度代替8.如果您想要真正的幻想,

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

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

答案 1 :(得分:5)

如果你的速度更快,你可以使用中描述的技术 http://leetcode.com/2011/08/reverse-bits.html

def reverse_mask(x):
    x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1)
    x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2)
    x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4)
    x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8)
    x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16)
    return x

答案 2 :(得分:4)

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

如果您想关注this solution转换问题,则只需找到合适的numbits即可。您既可以手动指定,也可以计算用n.bit_length()表示整数n所需的位数(Python 2.7和3.1中的新增内容)。

然而,对于65,这将给你7,因为没有理由为什么65应该需要更多位。 (您可能希望向上舍入到最近的8的倍数...)

答案 3 :(得分:4)

def reverse_int(x):
    result = 0
    pos_x = abs(x)
    while pos_x:
        result = result * 10 + pos_x % 10
        pos_x /= 10
    return result if x >= 0 else (-1) * result

我们并不需要将整数转换为二进制,因为整数在Python中实际上是二进制的。

逆转的想法就像做整数的空间逆转一样。

<<1

对于每个循环,原始数字正在丢弃最右边的位(以二进制形式)。当添加新位时,我们得到最右边的位并在下一个循环中乘以2({{1}})。

答案 4 :(得分:3)

您可以使用移位和遮罩测试数字的第i位。例如,65的第6位是(65 >> 6) & 1。你可以通过向右移动1次来以类似的方式设置一个位。这些见解为您提供了这样的代码(在'n'位的字段中反转x。)

def reverse(x, n):
    result = 0
    for i in xrange(n):
        if (x >> i) & 1: result |= 1 << (n - 1 - i)
    return result

print bin(reverse(65, 8))

答案 5 :(得分: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))

答案 6 :(得分:1)

通常,需要对数字数组应用此操作,而不是对单个数字进行此操作。 为了提高速度,最好使用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

速度较慢,但​​更易于理解(基于solution proposed by Sudip Ghimire):

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

答案 7 :(得分:0)

另一种方法是从两端循环比特并互相交换。这是我从EPI python书中学到的。

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))

答案 8 :(得分:0)

一种效率低下但简洁的方法,可在Python 2.7和Python 3中使用。

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

例如:

>>> bit_reverse(65, 8)
130

答案 9 :(得分:0)

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

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]