【C++中的高效运算】求最接近当前整数的2的n次方

315 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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,大家也不妨自己拿一个小例子自己试试看哦~

如果觉得我的内容对你有帮助,请点赞支持以下哦,感谢~