一:和十进制除法类似:只适用于正整数。负数(可以转为无符号类型计算)
参考我们之前要取下十进制数字上的一位用的是取模10和除10,由于十进制转换为二进制就是用除2取余法,所以我们只要判断取出的余数是一还是零即可,但是这种方法不适用与负数,我认为是因为除2取余法背后的数学原理,还有负数在内存中的存储为补码有关,所以我们可以将a转为无符号类型,这样存储的负数补码就可以用除2取余数法了。
unsigned int a =0;
int count = 0;
int i = 0;
scanf("%d",&a);
while(a)//若a为零,则无需再取余数
{
if (a % 2)//若取出余数为零,不进入if,若为1,进入if
{
count++;
}
a /= 2;
}
printf("%d", count);
对于在验证编译器是如何处理-1/2的我还有些疑问,比如我用二进制除法演算的时候,结果的这个二进制位应该如何存储,显示,读者老爷如果有兴趣,可以私信讨论讨论。
二:拿1与检验数字n按位与
1 .拿这个数字n与1按位与(&),并移动数字1的二进制位
按位与规则:两个操作数的二进制位上均为1才为1,只要有一个操作数上的二进制位上为零,则该位结果为零。
int a = 1;
int n = 0;
int count = 0;
scanf("%d", &n);//输入要求二进制位1个数的数字
while (a)
{
if (n&a)//我们在这里用按位与操作符,如果n在a上唯一的1的二进制位上也为1,结果必定不为零,if进入,count++
count++;
a <<= 1;//if不控制此处的语句,因为不管n在对应位上是否为1,我们都要往下一位检验
//左移操作符左边抛弃,右边补零
}
printf("n二进制中1的有%d个", count);
(2)1与检验数字n按位与,右移动n
在用按位与操作符统计一个数上二进制位1的个数时,还可以不移动数字1,而移动要检验的n,我们此时可以用右移操作符把n上要检验
在编译器中右移操作符默认左边补符号位,右边抛弃,对于一个数在32位机器下我们只需要判断三十二次,当然移动n的这个方法也可以复用第一种方法代码,但是负数会因为左边一直补1而陷入死循环。
int a= 1;
int n = 0;
int count = 0;//计算retu二进制中1的个数
scanf("%d", &n);
int i = 0;
for (i = 0; i < 32; i++)
{
if ((count >> i) & 1)
count++;
}
printf("%d", count);
三 n与n-1按位与
例如1100与1011按位与,后结果为1000,1000与0111按位与为0,这说明数字n有多少个1就可以与进行多少次的n与n-1的运算
int c = 0;
int y = 0;
int sum = 0;
scanf_s("%d", &y);
while (y)
{
if (y - 1!=-1)
sum++;//加不加if都可,因为y!=0,那y至少大于1
y = y & y- 1;
}
printf("n二进制中1的有%d个", sum);
每次写博客的对我来说都是痛并快乐着,痛是有时候困顿在一些点上感觉自己描述不清楚,快乐是最后总算勉强能写完分享给大家,谢谢大家支持。