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

题目一:求一个整数的二进制序列中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的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第1张图片
如果输入一个负数呢?
求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第2张图片
显然结果是错误的,所以这种做法是有缺陷的对于负数无法测试。
给出第二种思路:使用右移操作符将每一位都移到最右边在与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的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第3张图片
这里用-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的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第4张图片
分析:将这个数和他下一个数按位与,可以每次将最右面的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;
}

结果:
求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第5张图片
这里测试时给出了一个比较特别的数字,可以用计算器自己定义一个序列然后进行测试。
思考如果这个题要求不使用数组来存放数组该如何做呢。
给出代码:

 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,结果正确 )
求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第6张图片

题目三:要求输出一个整数的每一位
分析:同样这道题我们也可以使用数组来存放这个整数的每一位数,然后输出每一位(注意:存放时是从右向左存放,那么输出时应该将数组逆序输出)

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;
}

求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第7张图片
如果不使用数组,只执行打印输出操作。


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;
}

求二进制序列中1的个数及奇偶序列+输出整数的每一位+两个数中多少个bit位不同_第8张图片
分析:两个数现进行按位异或得到一个二进制序列,两个数的某位相同则得到的序列中该位为0,某位相异则得到的二进制序列中该位为1,此时问题就转化为题目一,求出该二进制数列中1的个数即可。

你可能感兴趣的:(c阶段,c练习)