#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
这是预处理
int NumberOf1(int n)
{
int i = 0, j, m, count = 0, x;
x = n;
if (n == -2147483648)//一个只有补码的负数
return 1;
while (1)
{
if ((n % ((int)pow(2, i))) == n )
{
break;
}
i++;
}
i--;
for (j = i; j >= 0; j--)
{
m = n % ((int)pow(2, j));
if (m != n)
count++;
n %= (int)pow(2, j);
}
if (x < 0 && x % 2 == 0)
{
count = 32 - count;
}
if (x < 0 && x % 2 != 0)
{
count = 33 - count;
}
return count;
}
这是一种解决问题的函数,缺点,会有死循环,((int)pow(-2, i))这个值的结果是整形永远达不到那个数字2147483648,我们必须自己规定那个数字
-2147483648这个数字是int的最小值没问题,确实可以等于
((int)pow(-2, i)))这个数字不可以达到-2147483648,因为是正数,所以超出范围了,数字变为1,达到这个数字必须是正数到2147483648加负号,但是没办法,正数是达不到的
由于这个数字的特殊,我们得到10000000000000000000000000000000就是他的补码,即使我们用一些方法,比如说改变判断方式,设置整形不会超出范围,我们会得到这个二进制数(2147483648的无符号整形形态),导致他没有源码和反码,所以后面的公式对他无效。
反正就是很难受,int达不到2147483648,而这导致我们的任何运算结果(整形之间的计算,甚至加个负号,最后的结果都是整形)不能达到2147483648,这种方法的局限体现的淋漓尽致
导致我必须设立个别的入口
并且速度慢
int NumberOf2(int n)
{
int i = 0, count = 0;
for (i = 0; i < 32; i++)
{
if (n & (1 << i))
//只要1移位后二进制1所在的位置对应到n那边有1这个表达式结果就不会为0,如00000000000000000100000000000000非0
//如果对应的那个数字是0,则表达式结果为
count++;
}
return count;
}
法2:移位操作符<< >>
左移,出界删掉,末位补0
右移动,有符号补符号位,无符号补0;
(-2147483648的补码就是10000000000000000000000000000000,很特殊)
(不过这个方法就是可以直接用补码来判定,并且速度快)
(正数三个码都一样)(而法一是一次一次慢慢的算出源码(-2147483648算到了符号位,顶替了hhh,导致后面的混乱),然后通过转化,但是很遗憾,-2147483648不能转化)
int main()
{
int n = 0;
scanf("%d", &n);
system("cls");
printf("%d\n", NumberOf1(n));
printf("%d", NumberOf2(n));
return 0;
}
这是原函数