首页 > 编程语言 >java的位运算

java的位运算

时间:2023-10-24 19:05:14浏览次数:29  
标签:11111111 java 运算 00000000 补码 负数 原码

背景

最近公司有来面试的,和他们沟通过后,看到公司的面试题上有这么一个题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

总结

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

标签:11111111,java,运算,00000000,补码,负数,原码
From: https://blog.51cto.com/u_16321221/8009072

相关文章

  • Java基础 缓冲流
    缓冲流是高级流,它对基本流做了一个包装,所以在底层,真正读写数据的还是InputStream和OutputStream这两个基本流,只不过有了缓冲流的加持,读写的效率更高而已  ......
  • docker-compose 外部配置部署 java 项目原创
    有的项目写完,需要打包到不同的环境。所以配置一个外部yml配置文件会方便很多,不用重新打包。文件目录构造├──app├──application.yml├──app.jar├──Dockerfile├──mysql├──nginxdocker-compose.ymlw.sh复制DockerfileFROMjava:8#VO......
  • java.lang.OutOfMemoryError: Java heap space 一次堆内存溢出异常处理
    问题:在获取人员信息同步到系统中时出现了错误 Javaheapspace,解决:堆内存溢出,在网上查询了诸多资料,解决办法都是增加JVM的内存:JAVA_OPTS="-server-Xms2048m-Xmx2048m-XX:PermSize=256M-XX:MaxNewSize=512m-XX:MaxPermSize=512m" ,尝试增加内存后还是失败     ......
  • Java替换RequestBody和RequestParam参数的属性
    Java替换RequstBody和RequestParam参数的属性本文主要讲解在Java环境中如何替换RequestBody和RequestParam参数中的属性背景近期由于接手的老项目中存在所有接口中新增一个加密串来给接口做一个加密效果(项目历史原因,不方便上Jwt授权这套),所以就研究了一下Http请求链路,发现可......
  • 关于Windows打印机驱动相关问题-如何利用Java(或其他)调用打印机驱动程序完成原始文件翻
    前面这些都是问题描述,问题在偏下面场景:用户电脑上安装了PCL驱动,可通过驱动完成打印。需求:现在需要提供一种脱离PC端完成文件上传并打印的功能。让用户使用手机或pc未安装驱动时都能打印文件。目前思路:首先上传文件这一步没有任何问题,开发了相应的H5界面,通过浏览器进行原始文件......
  • C++算法:给表达式添加运算符
    题目给定一个仅包含数字0-9的字符串num和一个目标值整数target,在num的数字之间添加二元运算符(不是一元)+、-或*,返回所有能够得到target的表达式。注意,返回表达式中的操作数不应该包含前导零。示例1:输入:num=“123”,target=6输出:[“1+2+3”,“123......
  • 如何用Java找出两个List中的重复元素,读这一篇就够了
     在Java编程中,我们经常需要找出两个列表(List)中的重复元素。在本文中,我们将探讨三种方法来实现这一目标。 方法一:使用HashSetJava中的HashSet是一个不允许有重复元素的集合。我们可以利用这个特性,通过合并两个List并计算差集,来找出重复的元素。以下是一个通过使用HashSet数......
  • [VM] The JavaScript Virtual Machine
    TableofContentIntroudctiontoVMsCPU-UnderstandingthePysicalMachineVMs-Arrays,Objects,functions,prototypechainsDepotExplorer:collectingdatafromtheVMDeopt:CallingCoventions&InliningMegamohpism&InlineCache:Objectpro......
  • Java ConcurrentModificationException异常原因和解决方法
    JavaConcurrentModificationException异常原因和解决方法JavaConcurrentModificationException异常原因和解决方法在前面一篇文章中提到,对Vector、ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException异常。下面我们就来讨论以......
  • GO语言中的运算符
    算法术运算符运算符描述+相加-相减*相乘/相除%求余,仅限整数//arithmetic算术运算funcarithmetic(){ varafloat32=8 varbfloat32=3 varcfloat32=a+b vardfloat32=a-b varefloat32=a*b varffloat32=a/b ......