求一个整数存储在内存中的二进制中1的个数

这是一道经典的例题,众所周知数字在内存中以二进制的补码形式存储。二进制中只有1或0,所以我们就联想到了第一种方法。
一.先%后/法**(错误的)
思路;对于一个整数,例如123我们先取模(%)便可以得到它的最低位为3,然后再取余便可以去除它的最低位,得到12,。如此循环下去我们便可以得到它的各个位上的数字。由此可以类比出我们的第一种方法。对于二进制而言只有0或1,所以我们可以先令n(所要求的整数)%2得到最低位数再与1进行对比,如果想等的话count++(计数);如果不相等的话n/=2(更新),再重复上面的操作,直到n=0时结束循环,count的值为所求结果。
代码如下:

int count_one(int n)
{
     
	int count = 0;
	while (n)
	{
     
		if (n % 2 == 1)
		{
     
			count++;
		}
		n /= 2;
	}
	return count;
}

执行结果如下 假设输入6(110)
在这里插入图片描述
但这个方法有个缺陷,所以是错误的,上述可知数字在内存中以补码的形式存储所以-1位11111111111111111111111111111111(32个1)但用上述的程序运行的结果为0,那是因为循环体里的判断还有点问题,0%2==0,直接跳出了循环,所以count还是0。与我们想要的结果不符,所以这种写法是错误的。
在这里插入图片描述
方法二
以32平台为例,如果整数n与1按位与的话就可以获得整数最低位的值,再与1进行判断,如果相等则count++;接着再将n右移一位就可以获取下一个最低位的值,如此反复下去(32次即可结束循环),当循环结束时便,count的值便为所求的值。
代码如下:

//方法二
int count_one(int n)
{
     
	int count = 0;
	int i = 0;
	for (i=0; i < 32; i++)
	{
     
		if (((n >> i) & 1) == 1)
		{
     
			count++;
		}
	}
	return count;
}

程勋运行截图如下:
在这里插入图片描述

这个方法解决了-1的问题但效率有点低,需要循环32次,所以还需改进.

方法三
上边的方法二可以实现但效率太低,原因是整数的二进制中有许多的0,所以我们进行了改进,但这种方法不容易想到。当n&(n-1)时便可以消去一个最低位的1,有几个1便循环几次(也和0没有任何关系了),效率大大的提高了.当n为0使跳出循环,count的值即为所求的值。
代码如下

int count_one(int n)
{
     
	int count = 0;
	while (n)
	{
     
		n = n & (n - 1);
		count++;
	}
	return count;
}

程序运行结果如下
在这里插入图片描述

你可能感兴趣的:(C代码)