前言
今天准备写一下关于位运算的东西。
其实位运算并没有什么难点,也没有什么太多的内容。
啥也不说了,下面就直接进入文章正文。
初识位运算
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行.
这就是位运算的概念,不难理解吧。
位运算符号
含义 | Pascal语言 | C/C++语言 | Java |
---|---|---|---|
按位与 | a and b | a & b | a & b |
按位或 | a or b | a | b | a | b |
按位异或 | a xor b | a ^ b | a ^ b |
按位取反 | not a | ~a | ~a |
左移 | a shl b | a << b | a << b |
带符号右移 | a shr b | a >> b | a >> b |
无符号右移 | / | / | a>>> b |
这里各种语言都写在这里了。要用的话就那去吧。
下面说一说位运算符号的具体作用
符号使用方法
按位与
按位与,在c++的表示中为 &
位运算其实只有一种情况,用竖式两位对齐计算。下面是运算结果:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
也就是只有当两个数都是1的时候,按位与的结果才是1
按位或
按位或,在c++的表示中为 |
或运算的四种情况如下:
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
按位或就是只要两个数中有一个1的时候,按位或的结果就是1
按位异或(xor)
按位异或,在c++的表示中为^(不是乘方,我在刚学习c++是傻傻的认为是乘方)
按位异或的四种情况如下:
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
1 ^ 1 = 0
按位异或的结果很特殊,很容易迷惑人,相同是0,不同是1,不过有一个比较好的计算方法,你把他当做一个不进位的加法就可以了。
按位取反
这个似乎用的不多,理解就好:~
1. 所有正整数的按位取反是其本身+1的负数
2. 所有负整数的按位取反是其本身+1的绝对值
3. 零的按位取反是 -1(0在数学界既不是正数也不是负数)
左移
左移符号就是cout <<
左移怎么讲呢……
就是这样,举个栗子:8 << 2
就是说把8转为2进制:1000
然后在后面添加两个0:100000
也就是32;
其实计算这个并不难;
用数学表达就是a << n = a*2^n(这里的^是乘方嘿嘿)
右移
右移符号就是cin >>
右移同上,就是往右移动两位
不说了
位运算的计算技巧
统一特点
可以使用交换、结合律
按位与
可以使用按位与判断奇偶数
n & 1的结果就是取n的二进制的最末位。二进制的最末位为0表示n为偶数,最末位为1表示n为奇数。
有人可能会说,判断奇偶为什么不用%2?
其实用&1的方法比%2要快一些,如果追求速度,推荐使用&1,再说打字难度也是一样的。
按位异或
异或结果特点
1.n^n=0
2.0^n=0
异或翻转二进制
只需要将想要反转的位异或1就可以, 如: 1010 ^ 1111 = 0101
左移
左移当乘号
前面说过了……
n<<a=n*2^a
右移
右移当除号
n>>a=n/2^a
实战演练
问题1
一个奇数次
飞机场:http://www.51nod.com/Challenge/Problem.html#problemId=2106
问题2
二进制距离之和
飞机场:http://www.51nod.com/Challenge/Problem.html#problemId=2493
问题3
最优填充
飞机场:http://www.51nod.com/Challenge/Problem.html#problemId=2533
问题4
区间xor(xor表示异或)
飞机场:http://www.51nod.com/Challenge/Problem.html#problemId=2653
这个题目数据较水,正解的话还是要考虑一下的。
后记
这篇文章就到这里了。
如有问题随时在评论区问我!
客官,给个赞再走呗?