求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同

来源:互联网 发布:ssh弱算法支持 漏洞 编辑:程序博客网 时间:2024/05/19 12:16

题目一:求一个整数的二进制序列中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的个数即可。

阅读全文
0 0
原创粉丝点击