【落羽的落羽 C语言篇】二进制·其之二

在这里插入图片描述
上一期 二进制·之其一

一、不创建第三个变量,完成两个整数a,b的交换

不使用位操作符,其实也可以解决这个问题,如下:

int a = 1145;//a1
int b = 666;//b1
a = a + b;//a2 = a1+b1
b = a - b;//b(换) = a2-b1 = a1+b1-b1 = a1
a = a - b;//a(换) = a2-b(换) = a1+b1-a1 = b1 

但存在一个问题:倘若a,b很大,a2就存在溢出的风险

为了规避这个风险,可以利用^的特点:在这里插入图片描述
也可以实现这个功能:

int a = 1145;//a1
int b = 666;//b1
a = a ^ b;//a2 = a1^b1
b = a ^ b;//b(换) = a2^b1 = a1^b1^b1 = a1
a = a ^ b;//a(换) = a2^b(换) = a1^b1^a1 = b1

可惜的是,这种方法也存在局限性,它只能交换整数,不过它真正的价值是给我们提供了解决问题的新思路。
在这里插入图片描述

二、将13的二进制序列的第五位改成1,输出十进制结果,再改回0

13的二进制序列(补码)为:00000000 00000000 00000000 00001011
要将它的第五位改成1,怎么办呢?
哎,我们可以想到 | 的特点:在这里插入图片描述那我们就可以找到序列(补码):00000000 00000000 00000000 00010000,将它和13进行按位或操作,不就完成了吗?
那么这个序列怎么得到呢?显然,它就是十进制数16,但与其换算它,不如直观看成1<<4,(1的补码是00000000 00000000 00000000 000000001)也是一样的。
所以,将第五位改成1的代码就可以写成:

int a = 13;
a = a | (1<<4);

而到了改回去的时候,其实就是想把第五位改成0,实际是和前面完全相反的操作,我们可以使用按位与
在这里插入图片描述

代码为:

int a = 13;
a = a | (1<<4);
a = a & ~(1<<4);// ~(1<<4)是序列11111111 11111111 11111111 11101111

灰常好理解!
在这里插入图片描述

三、求一个整数存储在内存中的二进制中1的个数

有了前面的理解,想必这个问题你也能很快思考出解决问题吧(乐)
咳,直接说吧,众所周知,1的二进制是00000000 00000000 00000000 00000001,,如果这个整数num的最后一位是1,那么num&1就等于1(真),反之则等于0(假)。所以我们要做的,就是让num的二进制的每一位都走到最后一位来检测一下,循环就能轻松做到这个事情。

int num = 666int count = 0for(int i=0 ; i<32 ; i++)
{
if( (num>>i) & 1 )
  count++;
}

这样,最后count的值就是我们想要的答案了。

这应该是大多数人能想到的方法了,但其实还有一种优化的方式,规避了这个方式必须循环32次的冗杂:

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

num = num&(num-1)这个表达式,能把num的二进制的最靠右的1去掉,在num变成0之前,这个表达式能执行几次,就说明num中有几个1

举个栗子:
设n = 14(十进制数字)
以下数字都是省略前面的0的二进制
n = 1110
n-1 = 1101
n1 = n&(n-1) = 1100
n1-1 = 1011
n2 = n1&(n1-1) = 1000
n2-1 = 0111
n3 = n2&(n2-1) = 0
那么,n&(n-1)执行了三次,就说明n里有3个1。

这种方法是不是很好?是不是效率很高?可惜的是,我们大部分人都没办法自己想出来这个办法,对吧?
不过,今天你学到了,就可以悄悄记住,以后再遇到类似的问题直接使用,就很nice!
在这里插入图片描述

本篇完,感谢阅读,
敬请期待——长篇连载《指针》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值