一、根据进制特性,得到二进制中每一位
如果想得到2进制中的每一位,不如先看看10进制中的每一位怎么得到
给出一个10进制的数,怎么得到每一位呢?
思路:
比如15
15%10=5(得到个位数) 15/10=1(去掉个位数)
再用1%10=1(再次得到个位数) 1/10=0(再次去掉个位数)
所以我只要它是个循环就好了,直到最后的结果为0——终止循环
(注意上述计算是在c语言规定的所计算,15为int型变量,所以1/10=0)
那么对于10进制的操作,对于2进制同样适用!
思路:
以15为例
15%2=1(得到一个二进制位) 15/2=7(去掉刚得的二进制位)7%2=1(再次得到一个二进制位) 7/2=3(去掉刚得到的一个二进制位)3%2=1 3/2=1 1%2=1 1/2=0
故15的二进制数为1111
故不断循环即可,终止等于0就不用继续了,条件就是结果==0——终止循环
也就是%2 /2,得到每个二进制位后再去除即可
但这种情况对于正数是满足的,但对于负数不适用。
本质原因:while循环的判断条件是判断该数是否为0
以-1为例,第一次-1能进入while循环,但在循环内计算-1/2=0,下次循环无法进入,但-1符号位的1没有计算到
那就让这个符号位不妨碍我们就好了,直接把这个负数转为unsigned int,这个负数变成无符号数后会成为一个很大的数,但并不妨碍我们求正数和负数中二进制中1的个数
代码如下:
#include<stdio.h>
int i(unsigned int n)//对于负数不适用,所以转为unsigned int
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;//得到一个二进制位就++
}
n /= 2;//去除此二进制位
}
return count;
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", i(n));
return 0;
}
2.利用移位操作符和位操作符
因为1的二进制只有最低位是1,所以再利用&操作符的特性,任何一个数与1&,都是这个数二进制位的最后一位&1的结果,所以我只要再利用>>操作符,让这个数的每个二进制位都和1&一遍,写个循环,我就可以知道1的个数了
#include<stdio.h>
int i(int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
//1是00000000 00000000 00000000 00000001
//&后除了最低项其他项均为0
if ((n >> i) & 1 == 1)//n>>i表示32位均有一次机会变成最低位
{
count++;
}
}
return count;
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", i(n));
return 0;
}
3.利用操作符执行几次就算出几个1
因为n与n-1 &几次,就会掉几个1(这个是可以验证的),所以只要看&几次就可以算出有几个1,直到n==0
#include<stdio.h>
int i(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", i(n));
return 0;
}