简体   繁体   中英

Slick way to reverse the (binary) digits of a number in Python?

I am looking for a slick function that reverses the digits of the binary representation of a number.

If f were such a function I would have

int(reversed(s),2) == f(int(s,2)) whenever s is a string of zeros and ones starting with 1.

Right now I am using lambda x: int(''.join(reversed(bin(x)[2:])),2)

which is ok as far as conciseness is concerned, but it seems like a pretty roundabout way of doing this.

I was wondering if there was a nicer (perhaps faster) way with bitwise operators and what not.

You could do it with shift operators like this:

def revbits(x):
    rev = 0
    while x:
        rev <<= 1
        rev += x & 1
        x >>= 1
    return rev

It doesn't seem any faster than your method, though (in fact, slightly slower for me).

How about

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

or

int(bin(n)[:1:-1], 2)

The second method seems to be the faster of the two, however both are much faster than your current method:

import timeit

print timeit.timeit("int('{0:b}'.format(n)[::-1], 2)", 'n = 123456')

print timeit.timeit("int(bin(n)[:1:-1], 2)", 'n = 123456')

print timeit.timeit("int(''.join(reversed(bin(n)[2:])),2)", 'n = 123456')
1.13251614571
0.710681915283
2.23476600647

Here is my suggestion:

In [83]: int(''.join(bin(x)[:1:-1]), 2)
Out[83]: 9987

Same method, slightly simplified.

I would argue your current method is perfectly fine, but you can lose the list() call, as str.join() will accept any iterable:

def binary_reverse(num):
    return int(''.join(reversed(bin(num)[2:])), 2)

It would also advise against using lambda for anything but the simplest of functions, where it will only be used once, and makes surrounding code clearer by being inlined.

The reason I feel this is fine as it describes what you want to do - take the binary representation of a number, reverse it, then get a number again. That makes this code very readable, and that should be a priority.

There is an entire half chapter of Hacker's Delight devoted to this issue (Section 7-1: Reversing Bits and Bytes) using binary operations, bit shifts, and other goodies. Seems like these are all possible in Python and it should be much quicker than the binary-to-string-and-reverse methods.

The book isn't available publicly but I found this blog post that discusses some of it. The method shown in the blog post follows the following quote from the book:

Bit reversal can be done quite efficiently by interchanging adjacent single bits, then interchanging adjacent 2-bit fields, and so on, as shown below. These five assignment statements can be executed in any order.

http://blog.sacaluta.com/2011/02/hackers-delight-reversing-bits.html

>>> def bit_rev(n):
...     return int(bin(n)[:1:-1], 2)
...
>>> bit_rev(2)
1
>>>bit_rev(10)
5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM