题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
分析:首先回顾一下补码:对于正数,补码与源码相同,对于负数,符号位取 1,剩下的 31 位(这里默认 int 型整数为 32 位)补码=源码取反+1。已知最高位为符号位,那么剩余 31 位决定正数与负数的大小。正数的最大值+1得到负数的最小值,补码的加减法带上符号位。
对于负数的补码,其二进制 = 2^32 + n(n < 0)。因为对于一个 正数 a,其对应负数 -a 的补码即为a的补数,即 a + (-a)= 2^32 。要理解这句话,需要理解补数,例如,若模为 12,则 8 和 -4 互为补数,5 和 -7 互为补数。在这里,模为 2^32 。互为补数就说明他们都代表着同一个数,只是在不同的进制(在这里为 10 进制)下有不同的表示,对于二进制来说,补数在二进制的表示下是相同的。
下面的代码是按取反加一的规则来的,但准确率 50% 都不到,不知道哪里错了,有知道的兄台麻烦告知一声。
int NumberOf1(int n) {
int A[32] = { 0 };
int flag = 0;
if (n < 0) {
flag = 1;
n = -n;
}
int i = 0;
while (n) {
A[i++] = n % 2;
n = n / 2;
}
if (flag == 1) {
A[31] = 1;
for (int i = 0; i < 31; ++i) {
A[i] = !A[i];
}
A[0] += 1;
if (A[0] == 2) {
A[0] = 0;
for (int i = 1; i < 32; ++i) {
A[i] += 1;
if (A[i] == 2) {
A[i] = 0;
}
else {
break;
}
}
}
}
int count = 0;
for (int i = 0; i < 32; ++i) {
if (A[i] == 1) {
count++;
}
}
return count;
}
后来,在牛客网上看到了一种更简单的方法,链接在这里:https://www.nowcoder.com/profile/562667/codeBookDetail?submissionId=1520125