带你真正的理解原码,反码,补码,取反

1,070 阅读4分钟

定义

  1. 计算机中存储的数值都是以补码形式存在的。
  2. 正数的原码,反码,补码都是一致的。
  3. 负数的原码是这个负数的绝对值的 bit位首位换为1,反码是首位不变,其余位置取反,补码是反码+1。
 public class Test{
    public static void main(String[] args){
        int a = 1000;
        /*
         *1000的二进制
         *正数的原码,反码,补码都是一致的
         00000000 00000000 00000011 11101000
        */
        int b = -1000;
        /*-1000的二进制
         原码: 10000000 00000000 00000011 11101000
         反码: 11111111 11111111 11111100 00010111
         补码: 11111111 11111111 11111100 00011000 也就是说-1000这个数在计算机中是这样存在的
        *
        */
    }
 }

取反是针对补码取反的;获取到的依然是补码

  1. 取反是针对所有bit位,反码是保持首位不变;
public class Test{
    public static void main(String[] args){
        System.out.println(~1000);
        //我们来分析整个过程
        /**
         * 00000000 00000000 00000011 11101000 => 1000的补码
         * 11111111 11111111 11111100 00010111 => 1000取反后的补码,在计算机中是这样存在的,如何获取到对外的表现形式呢?我们可以理解成负数的原码转换为补码的逆运算;
         * 11111111 11111111 11111100 00010110 => 针对这个补码 -1,获取到的是反码
         * 10000000 00000000 00000011 11101001 => 这就是1000取反后的补码对外的表现形式 -1001
         * 
         */
        System.out.println(~-1001); 
        /**
         * 1: 获取到-1001的对外表现形式
         * 10000000 00000000 00000011 11101001  => -1001的原码
         * 11111111 11111111 11111100 00010110  => -1001的反码
         * 11111111 11111111 11111100 00010111  => -1001的补码
         * 00000000 00000000 00000011 11101000  => 针对补码取反就是最终的结果 1000
         */
    }
}

我们在计算机中的运算到底发生了什么?

  1. 首先需要知道,数值在计算机中都是以补码的形式存在的,那么计算的元素自然也是补码,计算结果也是补码;
public class OutClass {
    public static void main(String[] args) {
       int a = 2;
       int b = -6;
       System.out.println(a+b);
        /**
         * 00000000 00000000 00000000 00000010 +1的补码
         * 10000000 00000000 00000000 00000110 -6的原码 
         * 11111111 11111111 11111111 11111001 -6的反码
         * 11111111 11111111 11111111 11111010 -6的补码
          用补码参与运算;
          00000000 00000000 00000000 00000010
        + 11111111 11111111 11111111 11111010 
        -----------------------------------------------------
          11111111 11111111 11111111 11111100 // 得到的是结果的补码,因为首位位1表示负数,我们要获取对外表现形式
          11111111 11111111 11111111 11111011 //补码减去1得到反码;
          10000000 00000000 00000000 00000100 //首位不变,其余位置取反得到原码 -4
         *
         */
    }
}