0基础学算法 第七弹 位运算
今天要讲的内容主要分为两个大块,一个呢就是位运算,另一个呢就是关于二进制的原码反码补码,位运算的应用也算是比较多的了,进行位运算有时候可以省略不少事情呢,当然,也不是说不会位运算就会天崩地裂,毕竟事实上,在学位运算之前,我都是用其他方法来强制性模拟位运算(当时我并不知道什么是位运算)不过多学一些也是好的,省事儿,而且更快
一,二进制的原码反码和补码
相信二进制没有人不熟悉的,逢二进一,一个二进制数由0和1组成,他的最高位就是他的正负符号,0是正数,1是负数,例如10001000,这就是一个负的二进制数,当然最高位是0就是正数
原码之所以叫做原码,必然是因为它就像是万物之源,补码、反码都是在他的基础上变化的,当最高位是0的时候,也就是正数的时候,原码==反码==补码
以下关于反码及补码的概念是基于最高位是1的情况(负数的情况)
反码,顾名思义,是原码颠倒过来的样子,除了最高位表示负号的那个“1”不变以外,其他的数位上的数 全部取反,1变0,0变1,假设原码为1001010100,它的反码就是1110101011,再假设原码是0111001,它的反码就是0111001,是不是有点奇怪,哈,我前面说过了,当原码是正数的时候,原码==反码==补码
补码,在原码是正数的情况下是等于原码或者反码的,但是在负数情况下,他恰好是反码加1,比如原码是100000,反码就是111111,补码就是1000000
二,进入正题,位运算
在系统的讲位运算之前,先给大家一张图表,方便大家查询
注明:位运算符号在c++中用法同算数运算符
首先是&
其实位运算不复杂,理解了就好,比如说&,把他理解成1代表true,2代表false,1&&2,明显为false(2),2&&2明显也为false(2),只有1&&1的时候才为true(1);
但是这是if语句里面的判断方法,而‘&’的运算方法是这样的,比如1010&0011,运算过程如下图
过程如右图
至于|的话。。。就是上下两个数只要有一个为1,结果就为1啦,如1100|0011=1111
‘~’!也比较好理解,做它的运算的时候,只需要传一个二进制数,针对每一位进行运算可以从在每一位上如~1001=0110;
^,亦或,算起来也比较简单,只要两位不相等,结果就为1,举例,1001^0101=1100
我觉得有图就不用我多讲了吧/狗头/滑稽
最后一组"<<"和”>>"这个是左移和右移的操作
请看
int类型的二进制是32位的,而long long是64位,左移和右移
例如,给出一个标准的32的int类型00000000000000000000000000000001,当我们使用左移的时候,整体忘左移,并在后面补零
右移也相似,只不过是低位被挤掉了,高位补0
有一道题,可以通过位运算做的很简便,但如果你不会位运算的话。。。就另当别论了
如果你不用位运算,你要写很复杂的代码,但是用了,你就只要10行代码,如假包换(虽然我绝对不换)
题目链接→https://www.luogu.com.cn/problem/P1100
看到题目,很清晰了,首先录入两个字符串,然后将它转成二进制,接着把前16位和后16位的数交换位置,最后结果转成十进制输出!好,完美。。。
停!
今天利用我们学的位运算压根不用这么麻烦!
直接用上我们的左移"<<"和右移">>"啊!
只要左移后16位,右移前16位不就好了?
废话不多说,大家请看最短代码!
#include<bits/stdc++.h> using namespace std; unsigned int x; int main(){ cin>>x;//录入x cout<<((x<<16)|(x>>16));//将左移16位后的x和右移16位的x用或"|"将他们重新连起来 return 0;//完美 }
完美撒花🎉🎉🎉🎉🎉🎉🎉
如果觉得我讲的不错的,麻烦点个关注➕,点个赞👍,以后还会持续更新的😀
ps:欢迎大家进群 群号:1031457671