啊我摔倒了..有没有人扶我起来学习....
前言
二进制(binary),发现者莱布尼茨,是在数学和数字电路中以2为基数的记数系统,是以2为基数代表系统的二进位制。这一系统中,通常用两个不同的符号0(代表零)和1(代表一)来表示。数字电子电路中,逻辑门的实现直接应用了二进制,现代的计算机和依赖计算机的设备里都使用二进制。每个数字称为一个比特(Bit,Binary digit的缩写)
一、问题的引出
- 假如有一个十进制数
15
,要统计它的二进制中1
的个数是多少,我们常用的做法是另外用一个1
和15
的二进制每一位去按位与(&
)
对应代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((15 >> i) & 1) == 1)
count++;
}
printf("%d", count);
return 0;
}
输出结果:
- 通过移位操作符和按位与操作符可以得到结果
二、巧妙的方法
- 我们给出一个表达式
n = n & (n - 1)
,我们来分析分析它的作用,随便假设一个数n
的二进制
n | 0000 0000 0000 0000 0000 ==1==000 0==1==00 000==1== |
---|---|
n-1 | 0000 0000 0000 0000 0000 ==1==000 0==1==00 0000 |
n&(n-1) | 0000 0000 0000 0000 0000 ==1==000 0==1==00 0000 |
紧接着继续再来一次
n | 0000 0000 0000 0000 0000 ==1==000 0==1==00 0000 |
---|---|
n-1 | 0000 0000 0000 0000 0000 ==1==000 00==11== ==1111== |
n&(n-1) | 0000 0000 0000 0000 0000 ==1==000 0000 0000 |
- 可以发现,每执行一次
n = n & (n - 1)
,n
最右边那个1
就会消失
于是修改代码如下:输入
15
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
int count = 0;
while (n)
{
n &= (n - 1);
count++;
}
printf("%d\n", count);
}
return 0;
}
输出结果:
三、另一个小细节
- 假如某个数,只执行一次
n = n & (n - 1)
,n
就为0
了,说明这个数是2
的倍数 - 因为它的二进制中只有一个
1
,消灭一次就没了,而二进制中只有一个1
的不就是2
的倍数嘛~