题目一:求一个整数的二进制序列中1的个数
分析:首先,我们知道数在内存中是以补码得形式储存的,而正数的原码补码反码都相同。
做法一:
int main()
{
int count = 0;
int num = 0;
printf("输入一个数:");
scanf("%d", &num);
while (num)
{
if (num % 2 == 1)
{
count++;
}
num = num / 2;
}
printf("1的个数为%d", count);
system("pause");
return 0;
}
//可以测试正数,负数无法测试
先来看结果:
如果输入一个负数呢?
显然结果是错误的,所以这种做法是有缺陷的对于负数无法测试。
给出第二种思路:使用右移操作符将每一位都移到最右边在与1按位与,结果为1说明原位为1;结果为0说明原位为0;
int main()
{
int i = 0;
int num = 0, count = 0;
printf("请输入一个数:");
scanf("%d", &num);
for (i = 0; i < 32; i++)
{
if ((num >> i) & 1 == 1)
{
count++;
}
}
printf("1的个数:%d", count);
system("pause");
return 0;
}
看结果:
这里用-1测试,我们都知道-1 的补码是32个1,结果正确。
思考这种方式是不是最好的呢?这种方式每次都要循环32次,效率很低。
在这里给出一种最简单的方式:
int main()
{
int i = 0;
int num = 0, count = 0;
printf("请输入一个数:");
scanf("%d", &num);
while (num)
{
count++;
num = num&(num - 1);//一个数与他下一个数按位与,可以去掉最右边的1,此时一个二进制数中有几个1,就循环几次,最坏情况是循环32次。
}
printf("1的个数为:%d", count);
system("pause");
return 0;
}
结果:
分析:将这个数和他下一个数按位与,可以每次将最右面的1去掉,即就是说一个数二进制序列中有几个1,就循环几次,效率非常高,最坏情况也只是循环32次。
题目二:求出一个数的奇偶序列
分析:很容易想到这个题可以先将每一位取出来存入一个数组,然后将奇数位输出,偶数位输出就好。
直接给出代码:
int main()
{
int a[32] = { 0 };
int num = 0;
int i = 0;
printf("请输入一个数");
scanf("%d", &num);
for (i = 0; i < 32; i++)
{
a[i] = num & 1;
num = num >> 1;
}
printf("奇数序列");
for (i = 31; i >= 0; i -= 2)
{
printf("%d", a[i]);
}
printf("\n");
printf("偶数序列");
for (i = 30; i >= 0; i -= 2)
{
printf("%d", a[i]);
}
system("pause");
return 0;
}
结果:
这里测试时给出了一个比较特别的数字,可以用计算器自己定义一个序列然后进行测试。
思考如果这个题要求不使用数组来存放数组该如何做呢。
给出代码:
int main()
{
int num = 0;
int i = 0;
printf("请输入一个数:");
scanf("%d", &num);
for(i=31; i>0; i-=2)
{
printf("%d ", (num>>i)&1);
}
printf("\n");
for(i=30; i>=0; i-=2)
{
printf("%d ", (num>>i)&1);
}
system("pause");
return 0;
}
显然这种方法更加简单,不需要借助数组,占用空间,我们只需要进行输出,这里给出测试结果,这里是用-1来测试的(32个1,即奇偶数列都为1,结果正确 )
题目三:要求输出一个整数的每一位
分析:同样这道题我们也可以使用数组来存放这个整数的每一位数,然后输出每一位(注意:存放时是从右向左存放,那么输出时应该将数组逆序输出)
int main()
{
int num = 0;
int count = 0;
int i = 0, tmp = 0;
int a[100] = { 0 };
printf("请输入一个数");
scanf("%d", &num);
tmp = num;
while (tmp)
{
count++;//整数的位数
tmp = tmp / 10;
}
for (i = 0; i < count; i++)
{
a[i] = num % 10;
num = num / 10;
}
for (i = count-1; i >= 0; i--)
{
printf("%d ",a[i]);
}
system("pause");
return 0;
}
void Print(int n)
{
if (n > 9)
{
Print(n / 10);//递归打印每一个数,将每一个数拆开并打印
}
printf("%d ", n % 10);
}
int main()
{
int num = 0;
printf("请输入一个数:");
scanf("%d", &num);
Print(num);
system("pause");
题目四:求出两个数的二进制序列中有几个bit位不同
int main()
{
int m = 0, n = 0;
int i = 0;
int count = 0;
printf("请输入两个数");
scanf("%d%d", &m, &n);
i = m^n;
while (i)
{
i=i&(i - 1);
count++;
}
printf("%d", count);
system("pause");
return 0;
}
分析:两个数现进行按位异或得到一个二进制序列,两个数的某位相同则得到的序列中该位为0,某位相异则得到的二进制序列中该位为1,此时问题就转化为题目一,求出该二进制数列中1的个数即可。