虽然本方法是java写的,但是其原理适用于大部分语言
方法一:通过取模%运算取出每一位比特位数值,再进行判断(该方法不可判断负数)
原理:
通过取模num % 2 == 1 取出该数的每一个二进制位数,再判断是否等于1
再通过 num /= 2 位移其数值的一个比特位
其中hasNextInt()的用法,请参考另一篇笔记详解Scanner中next()、nextInt()、nextLine()、hasNext()、hasNextInt()的使用方法及注意事项
如下图,求11二进制中1的个数:
代码如下:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int count = 0;
if(sc.hasNextInt()) {
int num = sc.nextInt();
while(num > 0){
if(num % 2 == 1){
count++;
}
num /= 2;
}
System.out.println("该数字二进制中1的个数为:" + count);
}
}
方法二:右移>>(该方法可判断负数)
原理:
该方法和方法一的原理是类似的,只不过将取模、除等的运算简化为右移了
右移相当于缩小到原来的1/2,二进制最右侧位舍弃,最左侧补符号位(正数补0,负数补1),但是因为每个数字均要判断32次,所以效率不高
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int n = sc.nextInt();
int count = 0;//记录1的个数
for (int i = 0; i < 32; i++) {
if(((n>>i) & 1) == 1){
count++;
}
}
System.out.println("该数字二进制中1的个数为:" + count);
}
方法三:无符号右移>>>(该方法可判断负数)
原理:二进制最右侧舍弃,最左侧无论正负数均补0
右移相当于除以2,当 n/2 == 0 时,就没必要再去判断前面多余的数字了,所以效率相对较高
注意:千万不要写成普通右移,普通右移会在左侧位一直补1,导致死循环
代码如下:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int n = sc.nextInt();
int count = 0;//记录1的个数
while(n != 0){
if((n & 1) == 1){
count++;
}
n >>>= 1;
}
System.out.println("该数字二进制中1的个数为:" + count);
}
方法四:n&(n-1)(该方法可判断负数)
原理:
如果两个数字对应二进制位都是1,则结果为1,否则结果为0
效率高,每次 n&(n-1) 都会少个1,所以有几个1就会&几次,如下图求7二进制中1的个数:
代码如下:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
int n = sc.nextInt();
int count = 0;
while(n != 0){
n = n & (n-1);
count++;
}
System.out.println("该数字二进制中1的个数为:" + count);
}