两个数的二进制数中不同位的个数和一个二进制数中1的个数问题

一.两问题的转化

乍一看,上面两个问题毫不相关,但我们深入考虑一下的话,就会发现,按位异或运算符 ^ (相同为0,不同为1)能够巧妙转化上述问题,只要将两数按位异或,就能找出两数中不同位的个数,问题就转化成了1的个数问题。

二.二进制数中1的个数

这个问题有多种解法,这里举出三种。


1.模二取余法

废话不多说的,上代码

int Count(unsigned int num)
{
	int count = 0;
	while (num)
	{
		if (num % 2 == 1)//得到最低位进行检测
		{
			count++;
		}
		num = num / 2;//去掉最低位
	}
	return count;
}

注:上述函数接收类型必须是无符号整数。-1的补码为(ffffffff)h

可以借助十进制理解

例如:1234

1234%10得到个位数4,再/10去掉个位数,再%10得到十位数3, /10再去掉十位数.......

同理:

一个无符号二进制数x , x%2得到最低位,/2去掉最低位,再%2得到次低位.......依次进行

直到都检测完。


2.位运算

int Count2(unsigned int num)
{
	int count=0;
	while (num)
	{
		if ((num & 1) == 1)
		{
			count++;
		}
		num = num >> 1;
	}
	return count;
}

注:上述函数接收类型必须是无符号整数。

有符号整数和无符号整数的右移运算是不一样的,无符号整数右移等同于逻辑右移,最高位补0,有符号整数右移最高位补符号位(正数补0,负数补1)。

如果接受对象是有符号整数,输入负数就会陷入死循环。最高位一直补1,无法退出while循环。

依次检验最低位是否为1,满足则加一,这种方法不够高效,需要每位都进行检验。


3.优化后的位运算

int Count3(int num)
{
	int count = 0;
	while (num)
	{
		count++;
		num = num & (num - 1);
	}
	return count;
}

注:这种方法不涉及移位运算,对函数接收值类型是否有无符号不要求。

假设一个二进制数为 00110000

  00110000 - 1

=00101111       &00110000   =   00100000

  00100000 -1

=00011111       &00100000   =   00000000

退出循环

我们发现,每次执行完num=num&(num-1)语句后,最后面的1都会消去。实际上这种方法就是每次都消去末尾的1直到全为0,好处是执行次数少,有几个1执行几次。


以上是我的个人理解,如有错误,欢迎指出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值