给一个整数,如何求得大于等于该整数的最小2次幂呢? 最近看ConcurrentHashMap的源码中有这么一段代码,这段代码就是解决这个问题的最好答案。现在我给大家来讲解一下这段代码的意思吧。
/** * Returns a power of two table size for the given desired capacity. * See Hackers Delight, sec 3.2 */ private static final int tableSizeFor(int c) { int n = c - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; }为什么先-1呢?原因很简单,如果一个数不是2的乘方,那么它本身减1之后,最高位的位置是不会变的,而我们后续会把最高位后的所有低位都变成1,所以这些低位本身是1或者是0都是不重要的。而如果输入数本身就是2的乘方,那么我们减1之后,最高位的位置会往右移动一位(剩余都是1),我们把它+1之后,又变成了它“原来的模样”,符合我们的要求。
首先一个整数肯定是32位那我就随机取一个数字,我用*表示我不知道这一位是1还是0都好这样更能说明问题。 0000 001x xxxx xxxx,右移1位, 0000 0001 xxxx xxxx,然后将两个数字进行或操作可得到 0000 0011 xxxx xxxx,右移2位; 0000 0000 11xx xxxx,再将这两个数字进行或操作; 0000 0011 11xx xxxx,右移4位; 0000 0000 0011 11xx,再将这两个数字进行或操作; 0000 0011 1111 11xx,右移8位; 0000 0000 0000 0011,再将这两个数字进行或操作; 0000 0011 1111 1111,在对这个数字进行+1; 0000 0100 0000 0000,得到最终答案。 从这个例子中我们很明显可以看出通过移位+或操作算出了最终的结果。 首先在计算机中位运算是最快的计算方式,所以这种算法固然是最快的;其次整个移位过程一直到右移16位结束,这是因为如果一个int型是32位,出去1位的符号位,剩下的有效表述数字大小的有31位,当执行右移16位结束后就可以完全保证每一位都被运算过。
如果这道题让求的是小于等于该整数的最小2次幂的话,只需要将刚才最终的计算结果右移1位就好。