位运算学习总结

2 篇文章 0 订阅
1 篇文章 0 订阅

位运算常用技巧

  • 乘/除2的值
n<<1;//n乘2
n>>1;//n除2
  • 判断一个数为奇数还是偶数
    因为二进制逢二进位,所以很显然最后一位决定了这个数的奇偶性,直接按位与1就可以判断出这个数的奇偶性了。
if(n&1)
{
    //n是奇数
}
else
{
    //n是偶数
}
  • 判断两个数符号是否相同
    这个也很简单,二进制第一位表示符号,所以符号相同就为0(正数),符号不同就为1(负数)。

if(n^m>=0)
{
    //n和m同符号
}
else
{
    //n和m不同号
}
  • 判断一个数的正负

因为二进制的第一位为这个数的符号,所以只需要把第一个数提取出来就可以知道正负了,直接右移31位即可。


if(n>>31)
{
    //n为正数
}
else
{
    //n为负数
}

位运算中的特殊技巧

  • 交换两个数

普通的交换两个数很常见,直接用一个中间变量temp,然后进行互换就可以了。不过如果现在要求不用中间变量,只用a和b这两个变量如何交换?就要用位运算来实现了。


a^=b;
b^=a;
a^=b;

可以这样做的原因是因为通过异或能使原数中的异或1的位改变(11=0,01=1),异或0的位不变。而若再进行一次操作,我们会发现,这些位又会翻转回去(01=1,11=0),这就意味着一个数与任意一个给定的数连续异或两次,值不变。
这样的话再回来看这个式子,我们会发现b=abb,a=aba,所以第一句a赋为a^b,之后再相互异或就可以交换了。

  • 对这个数二进制的第m位进行处理(从低位到高位

首先为了得到第m位的值,肯定是要将这个数右移(m-1)位,然后为了将其他多余的数清零,我们再进行&1的操作,就可以将第m位提取出来了。
如果是想改变第m位的值,那么就不能对这个数进行移动,因为这样会改变这个数的值。所以我们要对1向左移(m-1)位,然后再进行操作更改。如果要将第m位变成1,那么就n|(1<<(m-1)),这样就可以保证其余位不变改变第m位。如果要将第m位变为0,那么就n&~(1<<(m-1)),因为取反后就能得到除了第m位为0其余位都为1的一个数,这样再进行按位与计算就可以只改变第m位的值了。

(n>>(m-1))&1;//取n的二进制的第m位
n|(1<<(m-1));//将n的二进制的第m位改为1
n&~(1<<(m-1));//将n的二进制的第m位改为0
  • 计算一个数二进制中1的个数(BitCount算法)
    为了得到这个数二进制中有多少个1,可以依次从后向前找是不是1,然后全部遍历一遍,方法是可以通过将一个数flag赋为1,然后用这个数与要计算的数进行按位与计算,如果得到的结果不为0,则说明这一位是有一个1的,否则为0。然后再将flag向左移,一直左移到最大位,就可以将这个数中的所有1都筛出来了。
//普通
int bitcount1(int n)
{
	int cou=0;
	int flag=1;
	while(flag)
	{
		if(n&flag)
		{
			cou++;
		}
		flag=flag<<1;
	}
	return cou;
}
//快速
int bitcount2(int n)
{
	int cou=0;
	while(n)
	{
		n=n&(n-1);
		cou++;
	}
	return cou;
}

但是这样的话,每次找总共有几位必须要通过这个类型最大位数的遍历次数才可以找到答案。所以这里还可以再优化一下加快一下速度。假设我们要求的数是n,那么我们将n-1,就可以将n的二进制变为最后一位的1变为0,最后一位的1右边的0全部变为1的一个数。这样重复计算n=n&(n-1),计算的次数就是n这个数二进制中1的个数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值