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

目录

一、题目要求

二、解题思路

(一)方法一

1 ) .分析

2 ).代码演示

(二)、方法二

1 ) .分析

2 ). 代码演示


一、题目要求

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

通过题目我们可知,一个整数在内存中的二进制数位是这个整数的补码,因此求的是这个整数的补码中的1的个数。

二、解题思路

(一)方法一

1 ) .分析

换位思考,若寻求一个整数中1的个数,我们恐怕一开始想的便是将这个整数的各个位数分离,随后再用循环的方式,进行以此判断,并以此统计。

而将一个整数各个位数分离的方法,我们可以采用先 %10 后 /10的方法,前者取出最低位的数字,后者去除最低位的数次,并加以循环,我们便可以得到一个整数的所有位数。

列如:

123 %10 = 3 

123 / 10 =  12

12 % 10 =  2

12 / 10 = 1

1 % 10 = 1

1 / 10 = 0

当最后的答案得出0时,循环便已经结束了。

所以,我们可以采用这种方法,解决二进制数的各个位数的分离

例如:

 1111 - 15的二进制

15 % 2 = 1

15 / 2 =  7

111 - 7的二进制

7 % 2 = 1

7 / 2 = 3

11 - 3的二进制

………………………………

以此类推  

但是此方法在面对负数时会出现问题,于是,又产生了一个新的方法,使用>>和&.

&具有判断是否为1的功能,当配合>>使用,则可以判断每一位的数位是否为1

& 的功能详情在http://t.csdn.cn/mqp1G

于是有了以下的代码演示

2 ).代码演示

int main()
{
  int a = 0:
  scanf("%d"&a);
  int i = 0;
  int count = 0;
  for (i = 0;i < 32; i++)
  {
    if ((a >> i) & 1) == 1)//进行移位判断,利用了&的性质
     { 
       count++;//等于1的进行统计,不等于1的直接进入循环
     }
   }
  printf("%d\n",count);
  return 0;
}

(二)、方法二

1 ) .分析

例如:

int n = 13;

1101 -  n的补码

1100 -  n-1的补码

1100 - n & (n-1)的结果 ,令这个 n & (n-1)成为新的n

1100 - n的补码

1011 - n-1的补码

1000 - n&(n-1)的结果,令这个 n & (n-1)成为新的n

1000 - n的补码

…………………………

通过以上,我们得知新的n和老的n相比,二进制数位上的1在逐渐的减少,并且是从右往左的方向以此减少,所以,我们可以得到一个规律,n = n & (n-1) 在不断的减少二进制位数上的1.

所以,我们产生了以下代码。

2 ). 代码演示

int main()
{ int n = 0:
  scanf("%d",&n);
  int count = 0;
  while (n)
  {
    n =n & (n - 1);
    count++;
  }
  printf("%d\n",count);
  return 0;
 }

猜你喜欢

转载自blog.csdn.net/2301_76445610/article/details/132140044