原理#
现在我们使用的二进制码表示都很简单:1、2、4、8、16・・・・・・
仔细观察就可以发现:在一串二进制数中,如果只出现一个 1,它就是 2 的幂次方
代码#
或者
原理剖析#
方法一#
因为 2 的幂次方只有一个 1,我们只需要去掉最后一个 1 后判断是否等于 0 即可。
上面的代码就能够去掉最低位的 1,原理也很简单:减 1 会使最低位 1 变为 0,并在更低位产生 1,其他位不变。而与上自身之后,这些 1 和 之前的最低位 1 就会被清除掉。
但是 0 是一个特例,因此我们要把它排除掉:
方法二#
法二和法一类似,首先我们需要知道 v & -v
有什么用,v & -v
其实就是获取一个二进制数的从低位到高位的第一个 1 的位索引。以 111 为例,111 的补码为 001,111 & 001 = 001;以 110 为例,110 的补码为 010,110 & 010 = 010;
显而易见,如果一个数的位索引等于它本身,那么它就是 2 的幂次方。
Benchmark#
下面是使用 MacBook Air (M1, 2020) 和 Apple clang 13.1.6 得到的结果
下面是使用 i5-9500 和 gcc 8.5.0 (Red Hat 8.5.0-10) 在 CentOS-8-Stream 下得到的结果