持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情。 写文章不易,阅读之前请给我点个赞吧~
我们的目标是求大于等于当前整数 x 的最小的 2 的 n 次方,此处提供的代码短小精悍,十分高效,后文也附上了原理的解析,以及个人理解欢迎探讨,批评指正~
一、代码
首先给出代码
int getCeilPowerOfTwo(int num)
{
--num;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
return ++num;
}
说明:
>> 右移
二、示例及原理分析
这里我们举一个具体的例子来分析这个问题: 假设要求 160 这个数值最接近它的,且大于它的最小的 2 的 n 次方
-
x = 160;
转换成二进制:x = 1010 0000(二进制)
-
x |= x >> 1
等价与:x = (x | x >> 1)
等价与:x = ( 1010 0000 | 0101 0000)
= 1111 0000;
-
x |= x >> 2
等价与:x = (x | x >> 2)
等价与:= ( 1111 0000 | 0011 1100)
= 1111 1100
-
x |= x >> 4
等价与:x = (x | x >> 4)
等价与:x = ( 1111 1100 | 0011 1111)
= 1111 1111
-
x |= x >> 8
等价与:x = (x | x >> 8)
等价与:x = ( 1111 1111 | 0000 0000)
= 1111 1111
-
x |= x >> 16;
等价与:x = (x | x >> 16);
等价与:x = ( 1111 1111 | 0000 0000)
= 1111 1111
三、总结
算下来发现,我们拿到一个数 160,对应的二进制数为 1010 0000,通过计算我们知道大于它的最小的 2 的 n 次方就是 256,就是 2 的 8 次方也就是 1 0000 0000,可以看出 2 的 8 次方,就是数值 1010 0000 本身 1 的最高位的位数再左移 1,或者就是巧妙的运用了右移(速度快),和按位或运算(保证高位的1不会丢失,保证低位都是1)同样得到了2的8次方:1111 1111+1 = 1 0000 0000;
【注意】对于刚好是 2 的 n 次方的数字; eg. x = 256 =1 0000 0000; 本身就是结果,按照上面的方式运算结果为 1 1111 1111,再 +1 就大了,考虑到这种情况,所以最开始就要 -1,大家也不妨自己拿一个小例子自己试试看哦~
如果觉得我的内容对你有帮助,请点赞支持以下哦,感谢~