二进制中的一个数
题目描述
| 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 |
思路1
- 把一个整数减去1,再和原整数做与运算,会把该整数最右边的1变成0.那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。
程序(java)
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0) {
n=(n-1)&n;
count++;
}
return count;
}
}
思路2
- 首先把n和0x80000000做与运算,判断n的最高位是不是1.接着把n左移一位,再和0x80000000做与运算......如此将n反复左移,直到整个整数n变成0为止。即此问题变为判断一个整数的最左边是不是1.
程序(java)
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0) {
if((n&0x80000000)!=0) {
count++;
}
n=n<<1;
}
return count;
}
}
思路3
- 首先把n和1做与运算,判断n的最低为是不是1.接着把1左移以为得到2,再和n做与运算,就能判断n的低次位是不是1。如此反复,每次都能判断n的其中一位是不是1.
程序(java)
public class Solution {
public int NumberOf1(int n) {
int flag=1;
int count=0;
while(flag!=0) {
if((n&flag)!=0) {
count++;
}
flag=flag<<1;
}
return count;
}
}
补充(位运算)
- java里没有无符号(unsigned)整型。
- 位运算符
| No. |
运算符 |
描述 |
| 1 |
& |
按位“与” |
| 2 |
| |
按位“或” |
| 3 |
^ |
异或(相同为0,不同为1) |
| 4 |
~ |
取反 |
| 5 |
<< |
左位移 |
| 6 |
>> |
右位移 |
| 7 |
>>> |
无符号右位移 |
- 左移位(<<)、右移位(>>)
1). m<<n表示把m左移n位,在左移的时候,最左边的n位将被丢弃,同时在最右边补上n个0.0000 1010 << 2 = 0010 1000
1000 1010 << 3 = 0101 0000
2). m>>n表示把m右移n位,在右移的时候,最右边的n位将被丢弃。最左边位分两种情况:如果数字原先是一个正数,则右移之后在最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1.0000 1010 >> 2 = 0000 0010
1000 1010 >> 3 = 1111 0001
3). 右移位操作符(>>>)
无论正负,都在高位插入0.0000 1010 >>> 2 = 0000 0010
1000 1010 >>> 3 = 0001 0001
- 位运算的效率比乘除法及取余运算的效率要高很多。
- 十进制转二进制
负数转二进制:
1)、取负数的绝对值的原码;
2)、计算原码的反码;
3)、对反码加一,获取补码