C语言 编程题(操作符)

C语言学习!

1. 统计二进制中1的个数。

        写一个函数返回参数二进制中1的个数,

        比如:输入15 (0000 1111) 二进制有4个1,输出4.

方法1

编程思路:

得到十进制数字的每一位操作:

  • 如1234
  • 1234 % 10就可以得到原数字1234个位的4
  • 1234 / 10就可以去掉原数字1234个位的4得到123
  • 123 % 10就可以得到原数字1234十位的3
  • 123 / 10就可以去掉原数字1234十位的3得到12
  • 12 % 10就可以得到原数字1234百位的2
  • 12 / 10就可以去掉原数字1234百位的2得到1
  • 1 % 10就可以得到原数字1234千位的1
  • 1 / 10就可以去掉原数字1234千位的1得到0
  • 当数值为0时,不再计算。

最终就可以得到原数字1234的每一位数1、2、3、4。


得到二进制数字的每一位,可以参考上述方法

  • 如十进制数11的二进制数为1011
  • 11 % 2就可以得到1011最低位的1
  • 11 / 2 = 5就可以去掉原数字1011最低位的1得到101
  • 5 % 2就可以得到1011第二位的1
  • 5 / 2 = 2就可以去掉原数字1011第二位的1得到10
  • 2 % 2就可以得到1011第三位的0
  • 2 / 2 = 1就可以去掉原数字1011第三位的0得到1
  • 1 % 2就可以得到第四位的1
  • 1 / 2 = 0就可以去掉原数字1011第四位的1
  • 当数值为0时,不再计算。

最终就可以得到二进制数1011共有3个。

代码示例:

#include <stdio.h>

int Count_num(unsigned int n)
{
    int count = 0;
    while (n != 0)
    {
        if (n % 2 == 1)
        {
            count++;
        }
        n /= 2;
    }

    return count;
}

int main()
{
    int Num = 0;
    scanf("%d", &Num);
    int a = Count_num(Num);
    printf("%d\n", a);
    return 0;
}

运行结果:

15
4
-1
32

        但是这个方法计算负数的二进制1的个数需要注意。
例如-1

  • 1000 0000 0000 0000 0000 0000 0000 0001   原码
  • 1111  1111  1111 1111  1111  1111  1111 1110    反码
  • 1111  1111  1111  1111 1111  1111  1111 1111    补码

        -1在内存中是以补码的形式存放的,如果调用函数传参将有符号数-1当做为无符号数来看,就不会将数(-1补码)首位的1当做负数的符号位来看,而是将数(-1补码)当做一个很大的二进制数来看,就可以得到-1二进制数中1的个数。
        所以这里函数参数为无符号整型。


方法2

        一个数按位与1就可以得到一个数二进制位的最低位是几,让数的每一位都按位与1,就可以得到数二进制中1的个数。

代码示例:

#include <stdio.h>

int Count_num(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1) == 1)
		{
			count++;
		}
	}
	return count;
}

int main()
{
	int Num = 0;
	scanf("%d", &Num);
	int a = Count_num(Num);
	printf("%d\n", a);
	return 0;
}

运行结果:

15
4
-1
32

方法3

用表达式:n=n&(n-1) 来巧妙计算
 

代码示例:

#include <stdio.h>
int Count_Num(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}

int main()
{
	int Num = 0;
	scanf("%d", &Num);
	int n = Count_Num(Num);
	printf("%d\n", n);

	return 0;
}

运行结果:

15
4
-1
32

代码原理:

例如:n=15,表达式与表达式对应的二进制数值如下

第一次循环

  • 1111  n
  • 1110  n-1
  • 1110  n & (n - 1)

第二次循环

  • 1110  n = n & (n - 1)
  • 1101  n-1
  • 1100  n & (n - 1)

第三次循环

  • 1100  n = n & (n - 1)
  • 1011  n-1
  • 1000  n & (n - 1)

第四次循环

  • 1000  n = n & (n - 1)
  • 0111  n-1
  • 0000  n & (n - 1)

        当n=0时,二进制数中就没有1了,在n=0之前,表达式n = n & (n - 1)执行过几次,原数n的二进制数就有几个1,因为表达式执行一次去掉二进制数最右边的一个1.

2.求两个数二进制中不同位的个数。

        两个int(32位)整数m和n的二进制表达式中,有多少个位(bit)不同。

方法1

        m和n每一位都按位与1后比较是否相等。

代码示例:


#include <stdio.h>

int Count_diff_bit(int m, int n)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) != ((n >> i) & 1))
		{
			count++;
		}
	}

	return count;
}


int main()
{
	int m = 0;
	int n = 0;
	scanf("%d %d", &m, &n);
	int ret = Count_diff_bit(m, n);
	printf("%d", ret);
	return 0;
}

运行结果:

15
1
3
1
-1
31

方法2

        求出m与n异或的值后,再计算所得值的二进制位1的个数。

        异或:相同为0,不同为1.

代码示例:

#include <stdio.h>

int Count_diff_bit(int m, int n)
{
	int count = 0;
	int num = n ^ m;
	while (num)
	{
		num = num & (num - 1);
		count++;
	}

	return count;
}


int main()
{
	int m = 0;
	int n = 0;
	scanf("%d %d", &m, &n);
	int ret = Count_diff_bit(m, n);
	printf("%d", ret);
	return 0;
}

运行结果:

15
14
1
15
-1
28

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值