java的位运算
  rEMQtKeFkz9t 2023年11月02日 51 0

背景

最近公司有来面试的,和他们沟通过后,看到公司的面试题上有这么一个题5|2的结果是什么。然后被他们问到,我只知道是一个位运算题,具体的答案还真的不知道,作为技术人,求知的精神定然不能缺少;今天就来查缺补漏,对位运算进行一个回顾。

什么是位运算

位运算是对整数在内存中的二进制进行操作摘抄自百度百科。就是对二进制进行操作,操作效率高,但是不易理解。

有哪些位运算

  • a & b 与运算
  • a | b 或运算
  • a ^ b 异或运算
  • ~a 非运算
  • a << b 左移运算
  • a >> b 右移运算
  • a >>> b 无符号右移运算

运算的前提

因为运算是涉及到二进制,至少先要知道十进制和二进制的转换。 然后是要理解原码补码反码概念,因为计算机存放的不是二进制的原码,存放的是二进制的补码。注意:运算之前都要将原码转换为补码

原码

原码即转换为二进制最初始的值

  • 正数 5的原码(java int是32位):
    00000000 00000000 00000000 00000101
  • 负数 -5的原码(最左侧的1是符号位,1代表负)
    10000000 00000000 00000000 00000101

反码

正数的反码和原码是一样的,负数的反码就是原码取反(符号位不参与转换)

  • 正数 5的反码
    00000000 00000000 00000000 00000101
  • 负数 -5的反码
    11111111 11111111 11111111 11111010

补码

计算机用存放补码的原因很简单,让加法可以实现加减的操作。

正数的补码和原码是一样的,负数的补码是原码取反加1(符号位不参与转换)

  • 正数 5的补码:
    00000000 00000000 00000000 00000101
  • 负数 -5的补码
    11111111 11111111 11111111 11111011

补码转原码

补码: 11111111 11111111 11111111 11111011

转为原码,有两种方法:

  1. 逆向推回去
    先减一: 11111111 11111111 11111111 11111010
    取反: 10000000 00000000 00000000 00000101
    得出结果是 -5
  2. 按照原码转补码逻辑,再转一遍
    先取反: 10000000 00000000 00000000 00000100
    再加一: 10000000 00000000 00000000 00000100
    得出结果是 -5

开始运算

& 与运算

与运算:只有两个操作数对应位同为1时,结果为1,其余全为0

负数运算

题目: 5 & -2

  1. 转换为原码
    5 的原码:00000000 00000000 00000000 00000101
    -2 的原码:10000000 00000000 00000000 00000010
  2. 转换为反码
    5 的反码:00000000 00000000 00000000 00000101
    -2的反码:11111111 11111111 11111111 11111101
  3. 转换为补码
    5的补码:00000000 00000000 00000000 00000101
    -2的补码:11111111 11111111 11111111 11111110
  4. 进行运算
    00000000 00000000 00000000 0000010111111111 11111111 11111111 1111111000000000 00000000 00000000 00000100(这是补码结果)
    符号位是0,正数补码和原码一致,直接转换为十进制也就是 4
正数运算

题目 5 & 2

  1. 按照上述方法得出补码
    5的补码: 00000000 00000000 00000000 00000101
    2的补码: 00000000 00000000 00000000 00000010
  2. 进行运算
    00000000 00000000 00000000 0000010100000000 00000000 00000000 0000001000000000 00000000 00000000 00000000(这是补码结果)
    将结果转换为十进制是 0

| 或运算

或运算:两个操作数对应位有一个为1,结果为1;都为0,结果是0

负数运算

题目 -5 | 2

  1. 还是老样子先算出补码
    -5的补码: 11111111 11111111 11111111 11111011
    2的补码: 00000000 00000000 00000000 00000010
  2. 进行运算
    11111111 11111111 11111111 1111101100000000 00000000 00000000 0000001011111111 11111111 11111111 11111011(这是补码结果)
    需要注意,符号位是1,也就是负数的补码,负数的补码和原码不一样的,需要进行转换为原码。
    先取反: 10000000 00000000 00000000 00000100
    再加1: 10000000 00000000 00000000 00000101
正数运算

题目 5 | 2

按照之前的步骤,都转为补码,然后进行或运算;直接得出结果 7

~ 非运算

非运算,就是取反的过程,1取反为0,0取反为1

负数运算

题目 ~-5

  1. 转换为补码
    11111111 11111111 11111111 11111011
  2. 求非
    00000000 00000000 00000000 00000100(这是补码结果)
    结果转为十进制就是 4
正数运算

题目 ~5

按照原来的步骤,转补码,求非得出负数的补码,再将补码转为原码,得出结果为-6

^ 异或运算

两个同位的操作数,相同为0,相异为1

<< 左位移运算

a << b就是 a的补码向左移b个位数,低位的补零

正数运算

题目 5 << 2

  1. 将5转为补码
    00000000 00000000 00000000 00000101
  2. 向左移2位,且低位补零
    00000000 00000000 00000000 00010100(补位结果)
    得出结果为 20
负数运算

题目 -5 << 2

  1. 将-5转为补码
    11111111 11111111 11111111 11111011
  2. 向左移2位,低位补零
    11111111 11111111 11111111 11101100(补位结果)
    转换为原码 10000000 00000000 00000000 00010100
    得出结果为 -20

>> 右位移运算

和左移位运算相反,向右移,高位补零

>>> 无符号右位移运算

表示无符号右移,也叫逻辑右移;该数为正,则高位补0,而若该数为负数,则右移后高位同样补0

正数

正数的和 >> 的结果一样

负数

题目 -5 >>> 2

  1. -5 转为补码
    11111111 11111111 11111111 11111011
  2. 进行右移2位,高位补零,不管符号位
    00111111 11111111 11111111 11111110(补码结果)
    转为十进制为 1073741822

总结

之前总是畏惧位运算,因为涉及到了二进制;经过这两天的研究,发现没有那么难,主要是理解计算机存储的形式,然后按照计算机的逻辑进行推算,就可以得到结果。不过注意,计算要细心;最主要的一点是运算之前一定要转为补码

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

rEMQtKeFkz9t
作者其他文章 更多

2023-11-02