利用字节位操作如何判断一个整数的二进制是否含有至少两个连续的1 的方法有多种,大家第一反应应该想到的是以下的第一种方法。
方法一:从头到尾遍历一遍每一位即可找出是否有连续的1存在
这个方法是最普遍的、第一感觉就能想到的方法,下面我们看一下它的具体实现:
Python代码:
defmethod_1(n) :
last_is_one=False
this_is_one=Falsewhile n >0:
this_is_one= n % 2
if this_is_one andlast_is_one:returnTrue
n= n >> 1last_is_one=this_is_onereturn 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代码:
deffoo2(n):return (n & n<<1) > 0
那么,上面两种方法的效率差多少呢,我们来测试一下看看:
Python代码
deftest(func, loops):
b=time.time()for n inrange(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倍多:
1000000 , time cost: 0.6687741279602051
1000000 , time cost: 0.16364359855651855