位运算符使用规则
位运算符包括:位与(&)、位或(|)、位异或(^)、按位取反(~)、位左移(<<)、位右移(>>)
注意:位运算符是直接对整数对应的二进制数进行运算。所以第一步先求位运算的数字转换成二进制数,并且要将数字的位数补充到8位。如 32->100000->00100000
。
由于二进制内存储存数据的基本单位是字节(byte),一个字节由8个比特位(bit)组成。
位是描述电脑数据量的最小单位。所以在位运算之前要先将数字转换成二进制且补位到8
一.位与(&)运算
参与运算的两个值准备好(二进制八位)之后比较对应位置上的值。
-
如果对应位置的值都是1,则结果为1;否则为0。
-
如求:5&3。
对两个10进制数5和3进行位与运算
-
列出式子如下:
3=00000011(2) 5=00000101(2) ->00000001 //只有对应位置数字相同结果才是1 所以5 & 3 = 1(2)=1
二.位或(|)运算
参与运算的两个值准备好后,比较对应位置上的值。
-
如果对应位置只要有一个值为1,则结果就是1;当全部为0的时候结果才是0
-
如求:60(8)|17(8)
对两个8进制数60和17进行位或运算
-
列出式子如下:
60(8)=48=00110000(2) 17(8)=15=00001111(2) -------->00111111 //对应位置只要有一个是1结果就是1 所以 60(8) | 17(8)=111111(2)=63
三.位异或(^)运算
参与运算的两个值准备好后,比较对应位置上的值。
-
如果对应位置的值不同(一个是1一个是0),结果就是1;否则结果是0
-
如求:6A(16)^8(8)
对16进制数6A和8进制数8进行位异或运算
-
列出式子如下:
6A(16)=106=01101010(2) 8(8)= 8= 00001000(2) ---------->01100010 //对应位置不相同结果就是1,相同(同为0或同为1)结果就是0 所以 6A(16)^8(8)=1100010(2)=98
四.位取反(~)运算
按位取反是一元(单目)运算符,求一个整数对应的二进制数字的反码。(过程较复杂,分正负数两种情况)
(一)正数情况如下
将一个数字准备好后(转换成对应二进制并补位到8)
正数的转码顺序为(从8位二进制数开始):
集体取反码->得到有符号位的二进制数->符号位不变取反码->补码->结果
如求:~77(8) 对一个8进制正数77进行位取反运算
-
进制转换并补位到8:
77(8)=63=00111111(2)
-
取第一次反码:
00111111->11000000
第一次取反码后,得到数字的第一位是符号位(1表示负数,0表示正数) 11000000表示负数,所以最后的结果(十进制数)也是负数
-
接着再取反码,注意符号位不能变:
11000000->10111111
-
对第二次取反码的结果进行补码(在最后一位数字+1,注意是二进制下的+1)
10111111+1=11000000
-
所以最后的结果就是
-1000000(2)
,注意符号位不计入运算(符号位变为-) -
1000000(2)=64
,所以-1000000(2)=-64
-
所以
~77(8)=-1000000(2)=-64
如求:~5 对一个10进制正数5进行位取反运算
-
进制转换并补位到8:
5=00000101(2)
-
第一次取反码
00000101->11111010
第一次取反码后,得到数字的=第一位是符号位(1表示正数)
-
接着再取反码,符号位不能变:
11111010->10000101
-
对第二次取反码的结果取补码(最后一位加1)
10000101+1=10000110
-
最后的结果就是
-0000110
(符号位变为-) -
所以最后的结果:
~5=-110(2)=-6
(二)负数情况如下
同样将一个数字转换为二进制并补位到8。
负数的转码顺序为(从8位二进制数开始):
将负号放入数字中得到有符号位的二进制数->符号位不变取反码->补码->集体取反码->得到有符号位的二进制数->结果
如求:(~(-10)) 对一个10进制负数-10进行位取反运算
- 进制转换并补位:
-10=-(00001010)
- 将原数字所带的符号转换成符号位放入2进制数中
-(00001010)=10001010
- 第一次取反码
10001010->11110101
(符号位不能变) - 直接对第一次的反码进行补码(最后一位加1)
11110101+1=11110110
- 第二次取反码(符号位也变)
11110110->00001001
(变为正数) - 最后的结果就是
+0001001
(符号位变为+) - 结果
~(-10)=1001(2)=9
如求:(~(-015)) 对一个8进制负数-15(8)进行位取反操作
- 进制转换并补位:
-015=-13=-00001101
- 将原数字所带的符号转换成符号位放入2进制数中
-00001101=10001101
- 第一次取反码
10001101->11110010
(符号位不能变) - 直接对第一次的反码进行补码
11110010->11110011
- 第二次取反码(符号位要变)
11110011->00001100
(正数) - 最后的结果就是
1100(2)=12
- 所以
~(-(015))=12
五.位左移(<<)运算
将表达式写好之后,对运算符左边量(二进制数)的每一位全部向左移动N位(N是运算符右边的值)
顶出的高位舍去,空出的低位用0补其(正数和负数的操作都是用0补齐)
如求:21(16)<<2 16进制数21和2取左位移运算
- 进制转换并补齐
21(16)->33->100001(2)->00100001
- 所有数字向左移动2位
00100001->10000100
- 得到最终左位移的结果
10000100(2)->132
注意:移动位数超过8位后,继续向左移动,二进制数字的长度可以超过8位
如求: -33(8)<<3 8进制数-33和3取左位移运算
注意:对负数进行位移运算时,由于有符号位的存在,为了不干扰非符号位,一般将长度扩到到16位(甚至更长)
- 进制转换并补齐
-33(8)=-27=-(00011011)->1000000000011011
(长度为16且带符号位的二进制数) - 取反码(符号位不变)
1000000000011011->1111111111100100
- 补码
1111111111100100->1111111111100101
- 左移3位(符号位不能变)
1111111111100101->1111111100101000
- 低位减1(补码相反的操作)
1111111100101000->1111111100100111
- 取反码(符号位不变)
1111111100100111->1000000011011000
- 生成最终的二进制数
-(11011000)
- 得到
-(11011000)=-216
- 答案
-33(8)<<3=-216
!!!注意负数的位移操作步骤:转换为二进制带符号位的形式(16位)->取反码(符号位不变)->补码(加1)->按要求位移操作->低位减一(将二进制数减1,和补码操作正好相反)->取反码(符号位不变)->得到的二进制数就是结果(注意符号位最后变为负号,二进制数变为10进制数)->结束
六.位右移(>>)运算
将表达式写好之后,对运算符左边量(二进制数)的每一位全部向右移动N位(N是运算符右边的值)
移动时,分为两种情况:
- 对无符号数右移时,空出的空出的高位补0,顶出的低位直接舍去。(逻辑右移)
- 对带有符号的数字右移时,空出的高位全部以符号位填补。正数补0,负数补1(算术右移)
如求:23(8)>>3 8进制数23和3取右位移运算
- 进制转换并补齐
23(8)->19->10011(2)->00010011
- 所有数字向右移动3位
00010011->00000010
- 得到最终右位移的结果
10(2)->2
如求:-2B(16)>>2 16进制数-2B和2取右位移运算
负数的右位移方法步骤和负数的左位移方法相同,唯一的区别是:右位移在移动后将空出的高位用符号位(1)来填补!其余步骤完全相同! (为了阅读方便,转换成16位二进制数后每隔4位加一个逗号)
- 进制转换并补齐
-2B(16)->(-43)->(-101011)->1000,0000,0010,1011
- 取反码(符号位不变)
1000,0000,0010,1011->1111,1111,1101,0100
- 补码(最后位加1)
1111,1111,1101,0100->1111,1111,1101,0101
- 按要求右移动(右移2,空出的用1补齐)
1111,1111,1101,0101->1111,1111,1111,0101
- 低位减1(和补码的操作相反)
1111,1111,1111,0101->1111,1111,1111,0100
- 取反码(符号位不变)
1111,1111,1111,0100->1000,0000,0000,1011
- 结果
-1011(2)=-11
- 所以
-2B(16)>>2=-11