C语言入门 有关部分操作符的使用 求某个数字用二进制表达中有几个1的三种不同解法 (其中包含了 二进制相关内容,关系操作符>>.以及位操作符&(即按位与)的应用解释内容)

       求数字 15 以及数字-1的二进制表达式中有多少个一

目录

1.了解二进制表达

2.认识如何用代码计算数字的二进制中有几个一

                                   了解二进制的知识

1.首先了解整形数字是如何储存的

     拿整形数字 int a =15 (一个int 类型是4个字节,一个字节8个比特位 ,二进制中一个0或1占一个比特位所以一个整形a 需要用32个0.1来存储)

     例如:15 的二进制可表示为00000000 00000000 00000000 00001111

  2.    二进制转十进制的计算方法:从右往左数 第一个数字*2的0次方, 第二个数字*2的一次方,第三个数字*2的二次方,直至全部计算出来,再将其相加最后得到的值即为二进制转化成十进制的值)

        例如:那上面的15为例  1*2的零次方+1*2的一次方+1*2的二次方+1*2的三次方=15

     最左边的一位数字表示的是符号位(若数字位1则该数字为负数,若为0则为正数)

数据的储存使用的是二进制(正数储存的是源码,而负数储存的是补码(计算负数的二进制为有多少个1实际是计算其补码有多少个一)

  15 源码 00000000 00000000 00000000 00001111

   -1 源码      10000000 00000000 00000000 00000001

       反码       11111111 11111111 11111111 11111110(反码是源码的符号位不变其他位按位取反)

       补码        11111111 11111111 11111111 11111111  (补码是反码+1)(-1在存储中的样子)

                          

                           计算某个数字用二进制表示其中1的个数

     方法一: 用%2(取模符号)得到最右边数字  (若最右侧的一位为1的话则会模1;若为0则最右位为0)(每次取模后的得到的数为1是count++)

                    在将计算的数字/2(除以)得到该数字向右移一位的数字(舍弃最右边的一位)(此步是紧接这上一步操作,上一步判断最右位数字而这一步可以让第二位数字变成第一位,再进行判断改为数字)

详细看代码区

代码1

    只能用来计算正数

不能用来计算负数-1%2=0

                           -1/2=0

                   而-1的补码为11111111 11111111 11111111 11111111 

                    第一位为1 与计算机结果冲突故不能用来算负数

#include <stdio.h>
int count_one(int b)
{
	int count = 0;
	while (b!=0)
	{
		if (b % 2 == 1)   //b%2得到的是二进制最低为的值(即最右侧一位的值)
		{
			count++;  //最右侧为1 ,count++得到数a的二进制表达式中1的个数

		}
		b /= 2;    //b/2可看成二进制数列向右移了一位(则后续对其取模则是得到右侧第二位数字的值
	}
	return count;
}
int main()
{
	int a = 7;
	int ret = count_one(a);
	printf("%d\n", ret);
	return 0;
}

改进后的 代码2:该代码较代码中a的类型改为了无符号整型(即将-1的二进制表达是看成了一个有32个1的二进制位组合成的超大正数,最后计算-1的二进制中1个个数就可继续计算

int count_one(size_t b)  //用size_t b 接收a
{
	int count = 0;
	while (b != 0)
	{
		if (b % 2 == 1)   
		{
			count++; 

		}
		b /= 2;   
	}
	return count;
}
int main()
{  
	size_t a = -1;              //代码进行完善,将原先a的int类型转化成size_t(unsigned int)即无 
                                  符号整形的类型,使得该函数可以计算负数的补码中1的个数
	int  ret = count_one(a);
	printf("%d\n", ret);
	return 0;
}

 方法2:用右移>>符号和按位与&来计算1的个数

    右移符号>>:将数字向右移1为(去掉了最右位,最左侧补0)

     例如 a=15     00000000 00000000 00000000 00001111

          b=a>>1    00000000 00000000 00000000 00000111 (则b=7)

  数字与1按位与 (结果为1说明原数字最右位为1,为2则说明原数字为0)

     例如   a=10     00000000 00000000 00000000 00001010

              b=3       00000000 00000000 00000000 000000011

              c=1       00000000 00000000 00000000 000000001

 d=a&c                00000000 00000000  00000000 00000000 结果为0 ,a最右侧数字为0

e=b&c                  0000000 00000000 000000000 00000001 结果为1,则b最右位为1

思路:当a&1 为1是count++,右移31次(使得最后计算的最右侧数字是原先最左侧的数字为止)和按位与则可统计到该数中所有1的个数

int count_one(int a)
{
	int count = 0;
	int i = 0;
	for (i = 0;i < 32;i++)
	{
		if ((a >> i)&1 == 1)
		{
			count++;
		}
	}
	return count;
}
int main()
{
	int a = -1;     
	int  ret = count_one(a);
	printf("ret = %d\n", ret);
	return 0;
}

方法3:利用a与a-1 和按位与的方法

按位与&符号的说明 : 两个数字的二进制中对应位都为1是两数按位与得到的数值的该位也为1,若同为0或一个1一个0 则得到的数字的该位为0

                 例如:a=000001

                            b=000101

               则c=a&b= 000001

     a与a-1按位与的思路和意义                  

        a&(a-1)        (为了简洁,一下只写二进制的后4位)拿a=10为例

a     1010

a-1  1001                a&=(a-1)    则a在每次计算都发生改变

a     1000              按位与一次中的1个1少掉了

a-1  0111

a     0000             

   思路:按位与第二次的到的数也比之前少了个1(找计算规律)

               则可之与a-1按位与一次后a会少一个一

                则可以统计按位与的次数来计算a 数中1的个数,当a 等于0时跳出计算

即可得到该数中1的个数

int count_one(int a)
{
	int count = 0;
	while (a)      //巧妙之处当a=0时,while循环跳出
	{
			count++;
			a &= (a - 1);
		
	}
	return count;
}
int main()
{
	int a = 15; 
	int  ret = count_one(a);
	printf("ret = %d\n", ret);
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值