简体   繁体   English

光滑的方式来反转Python中数字的(二进制)数字?

[英]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 如果f是这样的功能我会

int(reversed(s),2) == f(int(s,2)) whenever s is a string of zeros and ones starting with 1. int(reversed(s),2) == f(int(s,2))每当s是一个零的字符串和一个以1开头的字符串。

Right now I am using lambda x: int(''.join(reversed(bin(x)[2:])),2) 现在我正在使用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: 我认为你当前的方法非常好,但你可以丢失list()调用,因为str.join()将接受任何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. 除了最简单的函数之外,它还建议不要使用lambda ,它只使用一次,并通过内联使周围的代码更清晰。

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. Hacker's Delight的整整半章专门针对这个问题(第7-1节:反转位和字节)使用二进制运算,位移和其他好东西。 Seems like these are all possible in Python and it should be much quicker than the binary-to-string-and-reverse methods. 看起来这些在Python中都是可能的 ,它应该比二进制到字符串和反向方法快得多。

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. 通过交换相邻的单个位,然后交换相邻的2位字段等,可以非常有效地完成位反转,如下所示。 These five assignment statements can be executed in any order. 这五个赋值语句可以按任何顺序执行。

http://blog.sacaluta.com/2011/02/hackers-delight-reversing-bits.html 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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