重磅!位运算符的深度总结详细讲解!

位运算符使用规则

位运算符包括:位与(&)、位或(|)、位异或(^)、按位取反(~)、位左移(<<)、位右移(>>)

注意:位运算符是直接对整数对应的二进制数进行运算。所以第一步先求位运算的数字转换成二进制数,并且要将数字的位数补充到8位。如 32->100000->00100000

由于二进制内存储存数据的基本单位是字节(byte),一个字节由8个比特位(bit)组成。
位是描述电脑数据量的最小单位。所以在位运算之前要先将数字转换成二进制且补位到8

一.位与(&)运算

参与运算的两个值准备好(二进制八位)之后比较对应位置上的值。

  1. 如果对应位置的值都是1,则结果为1;否则为0。

  2. 如求:5&3。对两个10进制数5和3进行位与运算

  3. 列出式子如下:

     3=00000011(2)
     5=00000101(2)
     ->00000001  //只有对应位置数字相同结果才是1
     所以5 & 3 = 1(2)=1
    

二.位或(|)运算

参与运算的两个值准备好后,比较对应位置上的值。

  1. 如果对应位置只要有一个值为1,则结果就是1;当全部为0的时候结果才是0

  2. 如求:60(8)|17(8)对两个8进制数60和17进行位或运算

  3. 列出式子如下:

     60(8)=48=00110000(2)
     17(8)=15=00001111(2)
     -------->00111111
     //对应位置只要有一个是1结果就是1
     所以 60(8) | 17(8)=111111(2)=63
    

三.位异或(^)运算

参与运算的两个值准备好后,比较对应位置上的值。

  1. 如果对应位置的值不同(一个是1一个是0),结果就是1;否则结果是0

  2. 如求:6A(16)^8(8)对16进制数6A和8进制数8进行位异或运算

  3. 列出式子如下:

     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进行位取反运算
  1. 进制转换并补位到8:77(8)=63=00111111(2)

  2. 取第一次反码:00111111->11000000

     第一次取反码后,得到数字的第一位是符号位(1表示负数,0表示正数)
     11000000表示负数,所以最后的结果(十进制数)也是负数
    
  3. 接着再取反码,注意符号位不能变:11000000->10111111

  4. 对第二次取反码的结果进行补码(在最后一位数字+1,注意是二进制下的+1)10111111+1=11000000

  5. 所以最后的结果就是-1000000(2),注意符号位不计入运算(符号位变为-)

  6. 1000000(2)=64,所以-1000000(2)=-64

  7. 所以~77(8)=-1000000(2)=-64

如求:~5 对一个10进制正数5进行位取反运算
  1. 进制转换并补位到8:5=00000101(2)

  2. 第一次取反码00000101->11111010

     第一次取反码后,得到数字的=第一位是符号位(1表示正数)
    
  3. 接着再取反码,符号位不能变:11111010->10000101

  4. 对第二次取反码的结果取补码(最后一位加1)10000101+1=10000110

  5. 最后的结果就是-0000110(符号位变为-)

  6. 所以最后的结果:~5=-110(2)=-6

(二)负数情况如下

同样将一个数字转换为二进制并补位到8。

负数的转码顺序为(从8位二进制数开始):
将负号放入数字中得到有符号位的二进制数->符号位不变取反码->补码->集体取反码->得到有符号位的二进制数->结果

如求:(~(-10)) 对一个10进制负数-10进行位取反运算
  1. 进制转换并补位:-10=-(00001010)
  2. 将原数字所带的符号转换成符号位放入2进制数中-(00001010)=10001010
  3. 第一次取反码10001010->11110101(符号位不能变)
  4. 直接对第一次的反码进行补码(最后一位加1)11110101+1=11110110
  5. 第二次取反码(符号位也变)11110110->00001001(变为正数)
  6. 最后的结果就是+0001001(符号位变为+)
  7. 结果~(-10)=1001(2)=9
如求:(~(-015)) 对一个8进制负数-15(8)进行位取反操作
  1. 进制转换并补位: -015=-13=-00001101
  2. 将原数字所带的符号转换成符号位放入2进制数中-00001101=10001101
  3. 第一次取反码10001101->11110010(符号位不能变)
  4. 直接对第一次的反码进行补码11110010->11110011
  5. 第二次取反码(符号位要变)11110011->00001100(正数)
  6. 最后的结果就是1100(2)=12
  7. 所以~(-(015))=12

五.位左移(<<)运算

将表达式写好之后,对运算符左边量(二进制数)的每一位全部向左移动N位(N是运算符右边的值)
顶出的高位舍去,空出的低位用0补其(正数和负数的操作都是用0补齐)

如求:21(16)<<2 16进制数21和2取左位移运算
  1. 进制转换并补齐21(16)->33->100001(2)->00100001
  2. 所有数字向左移动2位00100001->10000100
  3. 得到最终左位移的结果10000100(2)->132

注意:移动位数超过8位后,继续向左移动,二进制数字的长度可以超过8位

如求: -33(8)<<3 8进制数-33和3取左位移运算

注意:对负数进行位移运算时,由于有符号位的存在,为了不干扰非符号位,一般将长度扩到到16位(甚至更长)

  1. 进制转换并补齐 -33(8)=-27=-(00011011)->1000000000011011(长度为16且带符号位的二进制数)
  2. 取反码(符号位不变)1000000000011011->1111111111100100
  3. 补码1111111111100100->1111111111100101
  4. 左移3位(符号位不能变)1111111111100101->1111111100101000
  5. 低位减1(补码相反的操作)1111111100101000->1111111100100111
  6. 取反码(符号位不变)1111111100100111->1000000011011000
  7. 生成最终的二进制数-(11011000)
  8. 得到-(11011000)=-216
  9. 答案-33(8)<<3=-216
!!!注意负数的位移操作步骤:转换为二进制带符号位的形式(16位)->取反码(符号位不变)->补码(加1)->按要求位移操作->低位减一(将二进制数减1,和补码操作正好相反)->取反码(符号位不变)->得到的二进制数就是结果(注意符号位最后变为负号,二进制数变为10进制数)->结束

六.位右移(>>)运算

将表达式写好之后,对运算符左边量(二进制数)的每一位全部向右移动N位(N是运算符右边的值)

移动时,分为两种情况:

  1. 对无符号数右移时,空出的空出的高位补0,顶出的低位直接舍去。(逻辑右移)
  2. 对带有符号的数字右移时,空出的高位全部以符号位填补。正数补0,负数补1(算术右移)
如求:23(8)>>3 8进制数23和3取右位移运算
  1. 进制转换并补齐23(8)->19->10011(2)->00010011
  2. 所有数字向右移动3位00010011->00000010
  3. 得到最终右位移的结果10(2)->2
如求:-2B(16)>>2 16进制数-2B和2取右位移运算

负数的右位移方法步骤和负数的左位移方法相同,唯一的区别是:右位移在移动后将空出的高位用符号位(1)来填补!其余步骤完全相同! (为了阅读方便,转换成16位二进制数后每隔4位加一个逗号)

  1. 进制转换并补齐-2B(16)->(-43)->(-101011)->1000,0000,0010,1011
  2. 取反码(符号位不变) 1000,0000,0010,1011->1111,1111,1101,0100
  3. 补码(最后位加1) 1111,1111,1101,0100->1111,1111,1101,0101
  4. 按要求右移动(右移2,空出的用1补齐) 1111,1111,1101,0101->1111,1111,1111,0101
  5. 低位减1(和补码的操作相反) 1111,1111,1111,0101->1111,1111,1111,0100
  6. 取反码(符号位不变) 1111,1111,1111,0100->1000,0000,0000,1011
  7. 结果 -1011(2)=-11
  8. 所以 -2B(16)>>2=-11

总结:位运算中,最为复杂的是 位取反运算 和 负数的位移运算 。都涉及到 取反码、补码、低位减1 等操作,需要多次回顾!

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值