在Python中,如何用一行代码去判定整数二进制中的连续 1

 

利用字节位操作如何判断一个整数的二进制是否含有至少两个连续的1 的方法有多种,大家第一反应应该想到的是以下的第一种方法。

方法一:从头到尾遍历一遍每一位即可找出是否有连续的1存在

这个方法是最普遍的、第一感觉就能想到的方法,下面我们看一下它的具体实现:

Python代码:

def method_1(n) :                                                                                                               
    last_is_one = False
    this_is_one = False
    while n > 0:
        this_is_one = n % 2 
        if this_is_one and last_is_one:
            return True
        n = n >> 1
        last_is_one = this_is_one
    return False

 

上面的实现中,对于整数n先做取余运算(n % 2),如果余数为1,则n的最后一位是1,否则为0,并用this_is_one记录当前位;

然后判断一下,这次和上次的最后一位是不是都是1,如果是,则可以判定该整数有两个连续的1,否则把n向左移一位,继续循环开始的取余操作。

虽然通过上面第一种方法也可以实现,但是这样的操作复杂度大家都是可以看到的,比较耗时间,效率也较低。

下面这种方法在python中运行一行代码即可实现。

方法二:无需遍历每一位,但还是位操作:移一位(左移、右移皆可)然后和原数“位与”一下即可

这个原理不复杂,思考一下:

如果有两个连续的位为1,原数和移为后的数“位与”操作,就是会发生这两个连续的1进行“位与操作”,则结果中必出现至少一个位为1 (1&1 == 1),结果不为零;

如果没有至少两个连续的位为1,则1的两边都是0,原数和移为后的数“位与”操作,就是1与两边的0进行“位与操作”,则所有的1都变成了0 (1&0 == 0),结果必为零;

由以上推理,算法就简化的很多,只用一行代码即可搞定。

Python代码:

def foo2(n):
    return (n & n<<1) > 0 

 

那么,上面两种方法的效率差多少呢,我们来测试一下看看:

Python代码

def test(func, loops):
    b = time.time()
    for n in range(loops):
        func(n)
    e = time.time()
    print(loops, ', time cost:', e-b)


if __name__ == '__main__':
    test(foo1, 10**6)
    test(foo2, 10**6)

看一下运行结果,循环1百万次,方法二的速度是方法一的4倍多:

<function method_1 at 0x7f60de787e18> 1000000 , time cost: 0.6687741279602051
<function method_2 at 0x7f60de75b598> 1000000 , time cost: 0.16364359855651855

 

 

文章首发于我的技术博客猿人学Python基础教程

posted @ 2019-01-28 10:38  阿米扎  阅读(998)  评论(0编辑  收藏  举报