Java基础之原码,反码,补码,位运算符

简介: Java基础之原码,反码,补码,位运算符



前言

原码,反码,补码对于Java程序员来说是一个重点,也是对于初学者来说的一个难点,这里我给出一些简单易懂的规律与介绍(适合快速入门)。本篇内容是跟位运算符一起讲解的,正好可以做一些位运算符的习题来掌握原码,反码,补码的内容,也便于较好理解位运算符。


一、二进制在运算中介绍

  1. 二进制是逢2进1位的进位制,0、1是基本算符。
  2. 现代的电子计算机技术全采用的是二进制,因为它只使用0、1两个数字符号,非常简单方便,易于用电子实现。计算机内部处理的信息,都是采用二进制数来表示的。

二、原码,反码,补码(针对有符号的)

  1. 二进制的最高制位是符号位:0表示正数,1表示负数
  2. 正数(三码合一):原码,反码,补码都一样,均是该数的二进制数。
  3. 负数的反码:它的符号位不变,其他取反(0->1,1->0)。
  4. 负数的补码=它反码 +1,负数的反码=它补码 -1。
  5. 0的反码,补码都是0。
  6. java没有无符号数,换而言之,Java中的数都是有符号的。
  7. 在计算机运算的时候都是以补码的方式来运算的。(所以下面位运算符的运算都是先转为补码再操作)
  8. 运算结果还是要回归(转换)到原码。

三、位运算符

在讲述下面位运算符之前,我来解释一下高位,低位以,补位以及溢出这些词语的意思,方便大家更容易理解下面的内容。(右移为例(下面写错了,左移两位改为右移两位),如果看不懂就配合着下面7个位运算符的例子,大家就明白了)

Java有7个位运算符(&、|、^、~、>>、<<和>>>(特别注意没有<<<符号))

按位与&

两位全为1,结果是1,否则为0

//2 & 3 = 2
    2 的原码:00000000 00000000 00000000 0000010
       补码:00000000 00000000 00000000 0000010//正数三码一样
    3 的原码:00000000 00000000 00000000 0000011
       补码:00000000 00000000 00000000 0000011//正数三码一样
  2 & 3: 00000000 00000000 00000000 00000010
          00000000 00000000 00000000 00000011     //对补码进行竖向操作,0&0=0,0&1=0,1&1=1
        -----------------------------------------
          00000000 00000000 00000000 00000010//结果是补码,要转为原码
                            //正数三码一样,故还是这个
          =2

按位或 |

两位有一个为1,结果为1,否则为0

//2 | 3 = 3
    2 的原码:00000000 00000000 00000000 00000010
       补码:00000000 00000000 00000000 00000010//正数三码一样
    3 的原码:00000000 00000000 00000000 00000011
       补码:00000000 00000000 00000000 00000011//正数三码一样
  2 | 3: 00000000 00000000 00000000 00000010
          00000000 00000000 00000000 00000011      //对补码进行竖向操作,0|0=0,1|1=1,0|1=1
        -----------------------------------------
          00000000 00000000 00000000 00000011//结果是补码,要转为原码
                            //正数三码一样,故还是这个
        =3

按位异或 ^

两位一个为1,一个为0,结果为1,否则为0

//2 ^ 3 = 1
    2 的原码:00000000 00000000 00000000 00000010
       补码:00000000 00000000 00000000 00000010//正数三码一样
    3 的原码:00000000 00000000 00000000 00000011
       补码:00000000 00000000 00000000 00000011//正数三码一样
  2 ^ 3: 00000000 00000000 00000000 00000010
          00000000 00000000 00000000 00000011      //对两行补码进行竖向操作0^0=0,1^1=0,0^1=1
        -----------------------------------------
          00000000 00000000 00000000 00000001//结果是补码,要转为原码
                            //正数三码一样,故还是这个
        =1

按位取反 ~

0->1,1->0

// ~ -2 = 1
    -2 的原码:10000000 00000000 00000000 00000010
        反码:11111111 11111111 11111111 11111101  
       补码: 11111111 11111111 11111111 11111102 //反码+1
          =>11111111 11111111 11111111 11111110//逢2进1
      ~ -2:00000000 00000000 00000000 00000001   //对补码进行取反操作
                        //结果是补码,要转为原码
                          //最高位是0,为正数,三码一样
        =1

算术右移>>

低位溢出,符号位不变,并用符号位补溢出的高位。(本质:n>>m=n/2/2/…(除m个2))

//1 >> 2 = 0
    1 的原码:00000000 00000000 00000000 00000001
       补码: 00000000 00000000 00000000 00000001//正数三码一样
    1 >> 2:  00000000 00000000 00000000 00000000//对补码进行操作,整体右移两位,符号位补高位
                              //结果是补码,要转为原码
                              //最高位是0,为正数,三码一样
    ==>0   //本质:1 >> 2 ==>1/2/2=0

算术左移<<

符号位不变,低位补零。 (本质:n>>m=n22*…(乘m个2))

//1 << 2 = 4
    1 的原码:00000000 00000000 00000000 00000001
       补码: 00000000 00000000 00000000 00000001//正数三码一样
    1 >> 2:  00000000 00000000 00000000 00000100//整体左移两位,低位补零
                          //结果是补码,要转为原码
                              //最高位是0,为正数,三码一样  
    ==> 4  //本质:1 << 2 ==>1*2*2=4

逻辑右移>>>

低位溢出,高位补零。

//4 >>> 2 =1
    4的原码:00000000 00000000 00000100
       补码:00000000 00000000 00000100 
     4 >>> 2: 00000000 00000000 00000001//结果是补码,最高位是0,正数,三码一样,也是原码
       ===> 1
     对于正数,逻辑右移跟算术右移是一样的
     ----------------------------------------------------------------------
     而负数就不是这样,因为算术右移高位补符号位,所以正数补0,负数补1
     但是逻辑右移,高位均补0,这对正数没什么影响,但是对负数影响很大(因为补的高位由1变为0,即由正变负,转为原码时除符号位补的高位变成1)
     如 -2>>>2
     -2 的原码:10000000 00000000 00000000 00000010
        反码:11111111 11111111 11111111 11111101  
       补码: 11111111 11111111 11111111 11111102 //反码+1
          =>11111111 11111111 11111111 11111110//逢2进1
      -2>>>2:00111111 11111111 11111111 11111111  //整体右移两位,高位补0,结果是补码
         00111111 11111111 11111111 11111110  //转为反码
         01000000 00000000 00000000 00000001  //转为原码
                        //注意此时高位有1,这就变成了一个很大的数
        ==>2^30+2^0

上面算术右移的本质总结还不算太准确。就比如-2>>2= -1,按照本质的话-1/2/2=0,其实大家还是应该转换成补码去理解一下就懂了。

//这个本质不适用就是因为当它算术右移运算正好等于-1时(-n/2/2/...=-1),再右移多少位还是-1
    -1 的原码:10000000 00000000 00000000 00000001
        反码: 11111111 11111111 11111111 11111110
        补码: 11111111 11111111 11111111 11111111
        所以无论你再右移,按照算术右移规则:低位溢出,符号位不变,并用符号位补溢出的高位
        你的补码永远是11111111 11111111 11111111 11111111
        所以答案永远是 -1
    算术左移的本质总结是对的,大家可以用我上面的方法推导一下

总结

原码,反码,补码是一个必要的基础,希望把基础打好,才能走得更长远,学到后面越轻松,虽然你目前不一定用到,但是很重要,希望大家一定要注重基础的筑建,一起加油。如果大家把我这篇文章仔细弄懂,大家对这些内容的掌握就已经可以了,不需要再深入了。

相关文章
|
6月前
|
Java PHP
Java(八)位运算符~
Java(八)位运算符~
47 0
|
2月前
|
存储 Java 测试技术
Java零基础(22) - Java位运算符,了解一下!
【9月更文挑战第1天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
44 5
|
3月前
|
存储 Oracle Java
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
43 17
|
3月前
|
存储 Java 编译器
java的7种位运算符
java的7种位运算符
77 15
|
4月前
|
算法 Java 测试技术
day13:Java零基础-位运算符
【7月更文挑战第13天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
37 0
|
6月前
|
存储 Java 程序员
Java中的位运算符详解
Java中的位运算符详解
115 1
|
6月前
|
算法 Java
Java程序设计基础——位运算符简介
Java程序设计基础——位运算符简介
|
6月前
|
存储 算法 安全
滚雪球学Java(09-4):Java中的位运算符,你真的掌握了吗?
【2月更文挑战第2天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!
150 4
|
算法 Java 计算机视觉
深入解析Java中的位运算符:<<、>>和>>>
当谈到位运算符时,Java中的`<<`、`>>`和`>>>`运算符在源码中无疑是经常出现的。这些运算符在处理整数类型的数据时发挥着重要作用。它们主要用于对二进制位进行操作,是一种高效处理位级信息的方式。让我们深入探讨一下这些运算符的工作原理以及它们在Java中的应用。
105 1
深入解析Java中的位运算符:<<、>>和>>>
|
Java
JAVA位运算符
JAVA位运算符
63 0