第一种方式:使用模运算
/**
* 判断n是否是2的幂次方
*
* 一、
* 1 是 2的0次幂
* 2 是 2的1次幂
* 4 是 2的2次幂
* 8 是 2的3次幂
* 16是 2的4次幂
*
* 二、
* 2/2 商1 余0
* 4/2 商2 余0
* 8/2 商3 余0
* 16/2 商4 余0
*
* 假如一开始 n=16,那么执行步骤如下:
* while(16 >= 2 && 16 % 2 == 0) 该表达式为true,进入循环
* n = 16 / 2 执行完该段代码 n=8
* while(8 >= 2 && 8 % 2 == 0) 该表达式为true,进入循环
* n = 8 / 2 执行完该段代码 n=4
* while(4 >= 2 && 4 % 2 == 0) 该表达式为true,进入循环
* n = 4 / 2 执行完该段代码 n=2
* while(2 >= 2 && 2 % 2 == 0) 该表达式为true,进入循环
* n = 2 / 2 执行完该段代码 n=1
* while(1 >= 2 && 1 % 2 == 0) 该表达式为false,退出循环
*
* 接下来判断 n是否等于1:
* return n == 1; 1 == 1为true,返回true
*
* 结论:
* (1)如果n是2的幂次方,进入循环,在循环中不断地将n除2,那么循环结束n肯定等于1,最后返回true。
* (2)如果n不是2的幂次方,比如n=5,不满足循环条件while(5 >= 2 && 5 % 2 == 0),则不会进入循环,因为5%2等于1,接下来判断5 == 1,表达式为false,然后返回
*
* @param n
* @return
*/
public static boolean isPowerOfTwo(int n) {
if (n <= 0) {
return false;
}
if (n == 1) {
return true;
}
while (n >= 2 && n % 2 == 0) {
n /= 2;
}
return n == 1;
}
第二种方式:使用位运算
/**
* 使用位运算
*
* 假如n=16
* n的二进制数为: 1 0 0 0 0
* n-1的二进制数为: 0 1 1 1 1
*
* 那么,(n & (n - 1)) == 0,也就是 16 & 15 == 0
* 对应的二进制运算就是:
* 1 0 0 0 0
* 0 1 1 1 1 &
* 0 0 0 0 0
*
* 16&15的计算结果为00000
* 0的二进制数也是00000
* 所以,表达式为true
*
* @param n
* @return
*/
public static boolean isPowerOfTwo(int n) {
return n != 0 && (n & (n - 1)) == 0;
}