例如输入10进制数3,则2进制表示是0011,所10进制数3中1的个数是2
方法1
private static int numberOfOne(int num){
int count = 0;
// 变为正数(取反+1)
if(num < 0){
num = ~num + 1;
count++;
}
// 最右边是1,count++,右移一位
while(num != 0){
// num&1 > 0 代表最右边的数是1
if((num & 1) > 0){
count ++;
}
// 右移1位
num = num >> 1;
}
return count;
}
上述的方法是右移,可能会有疑问为什么不是左移。
因为num&1只能判断左右边是不是1的情况,如果左移,以0011为例子,需要与1000作&操作,是1000还是1000 0000或是1000 0000 0000都要通过计算获取
方法2
private static int numberOfOneV3(int num){
int count = 0;
// 变为正数(取反+1)
if(num < 0){
num = ~num + 1;
count++;
}
while(num != 0){
count ++;
num = (num - 1) & num;
}
return count;
}
其中的核心代码是
num = (num - 1) & num;
这个操作相当于减去最右边的1,无论是0011,还是0110
原理解析:
num最后一位是1,-1操作,1就会自然而然的被减去
num最后一位是0,-1操作,num最右边的1就会变成0,其余右边的0就会变成1,例如1000->0111
(num - 1) & num的&操作,num最右边的1变成0.
以上情况还是要考虑到负数的情况如何把负数变为正数,可以参考一下几种方法
1、取反+1(上面用的就是这个方法)
2、最后一位不变,其余取反
3、转成无符号数据类型(unsigned int)(-参数)(Java不支持无符号)