题目:求二进制中1的个数
请实现一个函数,输入一个int型整数,输出该数二进制表示中1的个数。
例:9的二进制表示为1001,1的个数为2。
分析:巧用位运算
方法1:从低位到高位逐位判断
已知int类型整数的范围有32位,可通过从低位到高位逐位判断是否为1来计数。
例如整数N,通过判断 N & 1 == 1得到最低位是否为1
通过判断 (N & (1 << 1)) == (1 << 1)得到第二位是否为1
可通过判断(N & (1 << i)) == (1 << i)得到第i+1为是否为1
(若结果为true则为1,否则为0)
方法2:逐位无符号右移依次判断最低位
与方法1类似,通过将原数的二进制形式逐位无符号右移,即从第二位起依次移动到最低位并与1相与,可得该位是否为1
可通过判断(N >>> i) & 1 == 1得到第i+1位是否为1
(若结果为true则为1,否则为0)
方法3:消除所有的1直到原数为0
依次将最低位的1到最高位的1消掉,最后结果为0时,记录消除操作的次数可得1的个数
知识补充:
1010 - 1 = 1001
1 0 0 1
& 1 0 1 0
= 1 0 0 0 - - - 消除了最低位的11000 - 1 = 0111
0 1 1 1
& 1 0 0 0
= 0 0 0 0 - - - 消除了下一位的1 --> 结果为0 消除2次 1的个数为2
总结: (x - 1) & x --> 这个操作可以消除最低位的1
代码展示
import java.util.Scanner;
public class Demo{
public static void main(String[] args) {
//实现键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入任意一个整数:");
//N为键盘录入的任意整数
int N = sc.nextInt();
//定义一个count变量,用于记录1出现的个数
int count = 0;
//获得N的二进制形式
String B = Integer.toBinaryString(N);
//使用方法1:逐位左移
for(int i = 0;i < 32;i++) {
if((N & (1 << i)) == (1 << i)) {
count++;
}
}
//输出N的二进制形式
System.out.println(N+"的二进制形式为:"+B);
//输出该数对应二进制形式的1的个数
System.out.println(N+"的二进制形式中1的个数为:"+count+"个");
//使用方法2:逐位右移
count = 0; //将方法1中使用过的count赋回0
for(int i = 0;i < 32;i++) {
if(((N >>> i) & 1) == 1) {
count++;
}
}
//输出该数对应二进制形式的1的个数
System.out.println(N+"的二进制形式中1的个数为:"+count+"个");
//使用方法3:消除所有1
int M = N;
count = 0;
while(M != 0) {
M = (M - 1) & M;
count++;
}
//输出该数对应二进制形式的1的个数
System.out.println(N+"的二进制形式中1的个数为:"+count+"个");
}
}
运行结果
骚话时刻:
位运算可真是个好东西
学学学,学到秃头