位运算
本篇为位运算的汇总所以略长,附上拆分开的链接
Part One 进制转换
Part Two 位运算符
Part Three 习题巧解
Part Three 习题巧解 之 1. 判断奇偶数
Part Three 习题巧解 之 2. 两数交换
Part Three 习题巧解 之 3. 只出现一次的数字
Part Three 习题巧解 之 4. 位1的个数
Part Three 习题巧解 之 5. 2的幂
Part Three 习题巧解 之 6. 4的幂
目录
Part One 进制转换
1. 什么是进制?
进制也就是进位计数制,是人为定义的带进位的计数方法。对于任何一种进制—X进制,就表示每一位置上的数运算时都是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。
2. 常用的进制有哪些?
人们最为习惯的是十进制(即逢十进一)
计算机内使用的是二进制(即逢二进一)
常见的还有八进制、十六进制(大于10的部分按ABCDEF顺序代替)
3. 进制之间的转换
3.1 八进制与二进制的互相转换
8 = 2 3 8=2^3 8=23即一个八进制数的一位对应一个二进制数的三位
相反的,一个二进制数的三位对应一个八进制数的一位
(不足三位时高位补0)
3.2 十六进制与二进制的互相转换
16 = 2 4 16=2^4 16=24即一个十六进制数的一位对应一个二进制数的四位
相反的,一个二进制数的四位对应一个十六进制数的一位
(不足四位时高位补0)
3.3 十进制与二进制的互相转换
十进制转换为二进制需要通过十进制数 ÷ \div ÷ 2 2 2取余(逆序读)
二进制转换为十进制
1000100101转换为549
常规运算:
1
1
1
×
\times
×
2
0
2^0
20+
0
0
0
×
\times
×
2
1
2^1
21+
1
1
1
×
\times
×
2
2
2^2
22+
0
0
0
×
\times
×
2
3
2^3
23+
0
0
0
×
\times
×
2
4
2^4
24+
1
1
1
×
\times
×
2
5
2^5
25+
0
0
0
×
\times
×
2
6
2^6
26+
0
0
0
×
\times
×
2
7
2^7
27+
0
0
0
×
\times
×
2
8
2^8
28+
1
1
1
×
\times
×
2
9
2^9
29=549
技巧:记住常用的几个2的幂数进而简化计算
Part Two 位运算符
1. 按位与运算&
1.1 按位与
根据二进制进行按位与&
&这个符号是键盘上5对应的符号,想要输入这个符号同时按住shift和5即可
1.2 运算
1.2.1 运算规则
a | b | a&b | 结论 |
---|---|---|---|
0 | 0 | 0 | 有0则为0 |
0 | 1 | 0 | 有0则为0 |
1 | 0 | 0 | 有0则为0 |
1 | 1 | 1 | 全为1则为1 |
1.2.2 二进制
0101&0100=0100(注:0101、0100均为二进制数)
1.2.3 八进制
47&33=3(注:47、33、3均为八进制数)
1.2.4 十进制
38&93=4(注:38、93、4均为十进制数)
1.2.5 十六进制
784&DBA=580(注:784、DBA、580均为十六进制数)
1.2.6 X进制
先将X进制数转换成二进制数,再进行按位与运算,最后再将结果转换成X进制数
2. 按位或运算|
2.1 按位或
根据二进制进行按位或|
|这个符号是键盘上\对应的符号,想要输入这个符号同时按住shift和*\*即可
2.2 运算
2.2.1 运算规则
a | b | a|b | 结论 |
---|---|---|---|
0 | 0 | 0 | 全为0则为0 |
0 | 1 | 1 | 有1则为1 |
1 | 0 | 1 | 有1则为1 |
1 | 1 | 1 | 有1则为1 |
2.2.2 二进制
0101|0100=0101(注:0101、0100均为二进制数)
2.2.3 八进制
47|33=77(注:47、33、77均为八进制数)
2.2.4 十进制
38|93=127(注:38、93、127均为十进制数)
2.2.5 十六进制
784|DBA=FBE(注:784、DBA、FBE均为十六进制数)
2.2.6 X进制
先将X进制数转换成二进制数,再进行按位或运算,最后再将结果转换成X进制数
3. 按位异或运算^
3.1 按位异或
根据二进制进行按位异或^
^这个符号是键盘上6对应的符号,想要输入这个符号同时按住shift和6即可(英文输入法)
3.2 运算
3.2.1 运算规则
a | b | a^b | 结论 |
---|---|---|---|
0 | 0 | 0 | 二者相同时结果为0 |
0 | 1 | 1 | 二者不同时结果为1 |
1 | 0 | 1 | 二者不同时结果为1 |
1 | 1 | 0 | 二者相同时结果为0 |
3.2.2 二进制
0101^0100=0001(注:0101、0100、0001均为二进制数)
3.2.3 八进制
47^33=74(注:47、33、74均为八进制数)
3.2.4 十进制
38^93=123(注:38、93、123均为十进制数)
3.2.5 十六进制
784^DBA=A3E(注:784、DBA、A3E均为十六进制数)
3.2.6 X进制
先将X进制数转换成二进制数,再进行按位异或运算,最后再将结果转换成X进制数
4. 左移<<
4.1 左移
根据二进制进行按位左移<<
<<这个符号是键盘上,对应的符号,想要输入这个符号同时按住shift和*,*两次即可(英文输入法)
4.2 运算
4.2.1 运算规则
左移是对一个数进行二进制的移位操作
左移1位可以理解为十进制数的$\times
2
操
作
左
移
n
位
可
以
理
解
为
十
进
制
数
的
2操作 左移n位可以理解为十进制数的
2操作左移n位可以理解为十进制数的\times$
2
n
2^n
2n操作
4.2.2 二进制
0101<<1=1010(注:0101、1010均为二进制数)
4.2.3 八进制
47<<1=116(注:47、116均为八进制数)
4.2.4 十进制
38<<1=76(注:38、76均为十进制数)
4.2.5 十六进制
784<<1 = F08(注:784、F08均为十六进制数)
4.2.6 X进制
先将X进制数转换成二进制数,再进行左移运算,(记得低位补0,)最后再将结果转换成X进制数
5. 右移>>
5.1 右移
根据二进制进行按位右移>>
>>这个符号是键盘上,对应的符号,想要输入这个符号同时按住shift和.两次即可(英文输入法)
5.2 运算
5.2.1 运算规则
右移是对一个数进行二进制的移位操作
右移1位可以理解为十进制数的$\div
2
操
作
右
移
n
位
可
以
理
解
为
十
进
制
数
的
2操作 右移n位可以理解为十进制数的
2操作右移n位可以理解为十进制数的\div$
2
n
2^n
2n操作
5.2.2 二进制
0101>>1= 0010(注:0101、0010均为二进制数)
5.2.3 八进制
47>>1= 23(注:47、23均为八进制数)
5.2.4 十进制
38>>1=19(注:38、19均为十进制数)
5.2.5 十六进制
784>>1 = 3C2(注:784、3C2均为十六进制数)
5.2.6 X进制
先将X进制数转换成二进制数,再进行右移运算,(记得高位补符号位,)最后再将结果转换成X进制数
6. 位运算表
a | b | a&b | a|b | a^b |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
全为1才为1 | 全为0才为0 | 二者相同为0不相同为1 |
Part Three 习题巧解
本篇为Part Three 习题巧解的所有题目汇总所以略长,附上拆分开的链接
Part Three 习题巧解 之 1. 判断奇偶数
Part Three 习题巧解 之 2. 两数交换
Part Three 习题巧解 之 3. 只出现一次的数字
Part Three 习题巧解 之 4. 位1的个数
Part Three 习题巧解 之 5. 2的幂
Part Three 习题巧解 之 6. 4的幂
1. 判断奇偶数
1.1 题目描述
【题目描述】
给定一个整数,判断该数是奇数还是偶数。如果n是奇数,输出odd;如果n是偶数,输出even。【输入】
输入仅一行,一个大于零的正整数n。【输出】
输出仅一行,如果n是奇数,输出odd;如果n是偶数,输出even。
1.2 思路讲解
思路讲解之前,请先思考一下除了一般做法的其他思路,尽量往位运算方面靠。
1.2.1 转成二进制
和位运算有关的题都建议先转成二进制再观察或者进行位运算符的操作得到规律
如下图所示,奇数转成二进制后最低位均为1,偶数转成二进制后最低位均为0
所以判断一个数是奇数还是偶数只需要知道它的最低位是0还是1
如果是0输出even,如果是1输出odd
1.2.2 运用位运算符
那么问题从判断奇偶转成怎么知道它的最低位是0还是1
由图上的举例可知任意数&1都等于这个数的最低位
(即&1操作是对最低位进行保留,其他位归零的操作)
原因:0&1=0所以偶数的最低位仍然是0而其余位进行&0会被归零
1&1=1所以偶数的最低位仍然是1而其余位进行&0会被归零
那么除了按位与&有这种特殊的意义,按位或|是否也有特殊的意义?
由图上的举例可知奇数|1等于这个数,偶数|1等于这个数+1
原因:0|1=1所以偶数的最低位会变成1而其余位进行|0会被保留
1|1=1所以奇数的最低位仍然是1而其余位进行|0会被保留
原来按位与&和按位或|有这种特殊的意义,那我们不难猜到按位异或^是否也有特殊的意义?
由图上的举例可知奇数^1等于这个数-1,偶数^1等于这个数+1
原因:0^1=1所以偶数的最低位会变成1而其余位进行^0会被保留
1^1=0所以奇数的最低位会变成0而其余位进行^0会被保留
1.2.3 总结
思路:任意正整数&1,如果是0输出even,如果是1输出odd
位运算符的技巧
正整数 | &1 | |1 | ^1 |
---|---|---|---|
奇数 | 1 | 原来的数 | 原来的数-1 |
偶数 | 0 | 原来的数+1 | 原来的数+1 |
1.3 代码实现
1.3.1 C语言
1.3.2 Java
2. 两数交换
2.1 题目描述
2.2 思路讲解
思路讲解之前,请先看清楚题意是不用临时变量,思考一下不用临时变量的做法尽量往位运算方面靠。
2.2.1 异或法
n^n = 0
0^n = n
两数交换的异或法
2.2.2 临时变量法
2.2.3 加减法
2.2.4 总结
异或法——效率高(难想到)
临时变量法——最常用到(易想到)
加减法——注意可导致int溢出(可理解为容器装不下会溢出)
位运算符的技巧
n^n = 0
0^n = n
2.3 代码实现
2.3.1 C语言
2.3.2 Java
3. 只出现一次的数字
3.1 题目描述
3.2 思路讲解
思路讲解之前,请先看清楚题意是其余数字出现了2次,请先思考一下除了一般做法的其他思路,做法尽量往位运算方面靠。
3.2.1 异或法
n^n = 0
0^n = n
将数组中所有的数进行异或即可得到只出现一次的数字
原因:出现两次的数字经过异或会被变成0,而只出现一次的数字会被保留下来
3.2.2 总结
思路:抓住此题的其余数出现的次数都是两次,使得可以使用位运算解决此问题
位运算符的技巧
n^n = 0
0^n = n
3.3 代码实现
3.3.1 C语言
3.3.2 Java
4. 位1的个数
4.1 题目描述
4.2 思路讲解
思路讲解之前,请先思考一下除了一般做法的其他思路,尽量往位运算方面靠。
4.2.1 二进制
4.2.2 位运算
思路:循环判断n=n&(n-1)之后n是否为0,若不为0继续进行n=n&(n-1),并且计数加一,若为0停止循环。
原因:n与n-1的二进制的不同之处在于最右边的1(及其)后面的部分,最右边的1前面都是一样的进行了保留,最右边的1&0=0而且最右边的1后面的部分只能是0或者没有,0&0=0或者0&1=0使得最右边的1(及其)后面的部分都归0
4.2.3 总结
思路:此题需要掌握n与n-1的二进制的不同之处使得可以使用位运算解决此问题
位运算符的技巧:n&(n-1)消灭了最右边的1
4.3 代码实现
4.3.1 C语言
4.3.2 Java
5. 2的幂
5.1 题目描述
5.2 思路讲解
思路讲解之前,请先思考一下除了一般做法的其他思路,尽量往位运算方面靠。
5.2.1 2的幂的特性
2的幂有什么特性呢?
2
0
=
1
2^0=1
20=1
2
1
=
2
2^1=2
21=2
2
2
=
4
2^2=4
22=4
2
3
=
8
2^3=8
23=8
研究一下上面的图示不难发现,2的幂有且仅有一个位为1
所以问题转换为位1的个数为1的情况。
注意:需要特判一下n<=0的情况,n<=0都不是2的幂
5.2.2 位运算
思路:判断n&(n-1)是否为0,若不为0则不是2的幂,若为0则是2的幂。
原因:如果n只有一位位为1的数,那么1后面的低位都是0,根据位为1的解题思路可得n&(n-1)必为0
5.2.3 总结
思路:此题需要掌握Part Three 习题巧解 之 4. 位1的个数的解题思路以及2的幂的特征方可解决此题
位运算符的技巧:n&(n-1)消灭了最右边的位为1的数
5.3 代码实现
5.3.1 C语言
5.3.2 Java
6. 4的幂
6.1 题目描述
6.2 思路讲解
思路讲解之前,请先思考一下除了一般做法的其他思路,尽量往位运算方面靠。
6.2.1 4的幂的特性
4的幂有什么特性呢?
4
0
=
1
4^0=1
40=1
2
2
=
4
1
=
4
2^2=4^1=4
22=41=4
2
4
=
4
2
=
16
2^4=4^2=16
24=42=16
2
6
=
4
3
=
64
2^6=4^3=64
26=43=64
研究一下上面的图示不难发现,一个数如果是4的幂,那么一定是2的幂,并且位为1的是偶数位(从0开始算)
所以问题转换为位1的个数为1并且位为1的是偶数位的情况。
注意:需要特判一下n<=0的情况,n<=0都不是4的幂
6.2.2 位运算
思路:先判断是否为2的幂,再判断位为1是否为偶数位
问题转换:从上一篇Part Three 习题巧解 之 5. 2的幂已经知道怎么求解2的幂,只需要在2的幂上判断位为1是否为偶数位,是则为4的幂,不是则不为4的幂
问题继续转换:判断位为1是否为偶数位,可以与0x55555555按位与,判断是否与原数相等,是则为4的幂,不是则不为4的幂。
原因:n&0x55555555是对偶数位进行保留,因为偶数位都是1,1&1=1、1&0=0都是对原有数位进行保留。而奇数位都是0,0&1=0、0&0=0都是对原有数位归为0。
问题也可转换:判断位为1是否为偶数位,可以与0xaaaaaaaa按位与,判断是否等于0,是则为4的幂,不是则不为4的幂。
原因:n&0xaaaaaaaa是对奇数位进行保留,因为奇数位都是1,1&1=1、1&0=0都是对原有数位进行保留。而偶数位都是0,0&1=0、0&0=0都是对原有数位归为0。
6.2.3 总结
思路:此题需要掌握2的幂的解题思路以及4的幂的特征方可解决此题
位运算符的技巧:
n&(n-1)消灭了最右边的位为1的数
n&0xaaaaaaaa是对奇数位进行保留
n&0x55555555是对偶数位进行保留
6.3 代码实现
6.3.1 C语言
6.3.2 Java
写在最后
系列位运算集结篇,你是否觉得位运算也有许多巧妙之处。希望看完这篇文档的你,能动手验证一下。纸上得来终觉浅,绝知此事要躬行。
文档分享
如果您觉得这份关于位运算的文档还不错,尝试点击分享这份文档给好友吧!
作者 @MythicalCreature
于2020 年 08月 20日发布