二进制中1的个数
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路
1)自然而然的思路:二进制数最后一位和1与运算,是1返回1,是0返回0;然后,右移一位【负数会引起死循环】
但是,在计算机中负数以补码存储时,符号位为1,右移最高位补1,最后会死循环(0xFFFFFFFF)
解决办法有2:
- 将二进制数转换成无符号数
- Java中有逻辑(无符号)右移操作符
>>>
,只对位进行操作,没有算术含义,它用0填充左侧的空位
算术右移不改变原数的符号,高位补符号位,而逻辑右移不能保证这点(负数会改变原数的符号)
2)逆向思维:将使用按位与运算判断原数某位是否为1的操作数左移,按位逐次比较
3)惊喜:(原数-1)& 原数,原数最后一位1变为0
总结:
- Java中没有unsigned
- Java中Int类型占4B(32b)
代码:
1)逻辑右移运算符>>>
public static int numberOf1(int n){
int count = 0;
while(n != 0){
if((n & 1) == 1)
count++;
n = n >>> 1;
}
return count;
}
2)与运算操作数左移
public static int numberOf1New(int n){
int count = 0;
int flag = 1;
//使用flag作为循环标志,移动32次之后,变成0(左移补0)
while(flag != 0){
//判断条件不能是 == 1
if((n & flag) != 0){
count++;
}
flag = flag << 1;
}
return count;
}
3)自操作
public static int numberOf1NewNew(int n){
int count = 0;
while(n != 0){
n = (n-1) & n;
count++;
}
return count;
}