微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

原码反码补码理解笔记

一、原码反码补码定义

  原码:是最简单的机器数表示法。用最高位表示符号位,‘1’表示负号,‘0’表示正号。其他位存放该数的二进制的绝对值。

  反码:正数的反码还是等于原码,负数的反码就是他的原码除符号位外,按位取反。

  补码:正数的补码等于他的原码,负数的补码等于反码+1。

正数

0

1

2

3

4

5

6

7

原码

0000

0001

0010

0011

0100

0101

0110

0111

反码

0000

0001

0010

0011

0100

0101

0110

0111

补码

0000

0001

0010

0011

0100

0101

0110

0111

负数

-0

-1

-2

-3

-4

-5

-6

-7

原码

1000

1001

1010

1011

1100

1101

1110

1111

反码

1111

1110

1101

1100

1011

1010

1001

1000

补码

10000

1111

1110

1101

1100

1011

1010

1001

二、为什么会有原码、反码、补码

     1  计算机只能存储0、1

     2  计算机中的运算只能计算“加法”,因此就把减法变成加法处理,如:1-1 = 1+(-1) ,但原码进行运算达不到减法的结果

         因此出现了反码和补码

三、深入理解补码,在十进制中看反码补码来理解二进制中的反码和补码

1)从时钟的角度理解减法转加法

  如果当前为8点,那么我们想要把时钟拨回到4点怎么处理呢? 2种办法,

方法一、8-4 即时钟向后拨回到4点,

方法二、8+4+4,即时钟向前拨到0点,然后在向前拨到4点,这个方法其实利用了表盘12个小时为一周的特点,这里的(4+4=8)就是-4的补码

            减法转加法的补码运算实际上是利用了溢出特性。

2)我们用4位数的二进制的运算,对比方法二中的时钟计算方式:

时钟一圈为满12(最小值1,最大值12)个小时 溢出,4位数的二进制满16(最小值0,最大值15),则溢出。

时钟中-4的补码为8 (8-4=8+8) ,-7的补码为5 ( 8-7=8+5 )

4位二进制中:-4的补码为1100( 十进制的 12 = 16-4 ),-7的补码为1001( 十进制的 9 = 16-7 )

3)从十进制中理解补码

  前提:0-9为一个周期,总共的数量为10个,过10就溢出丢掉

  则 8-5 = 8+补码(10-5) = 13 = 10分位为溢出丢掉 = 3 ;  -5的补码为5(反码和补码差1,因为原码算反码的时候使用最大值9计算的,但实际上有10个数字)

  9-2 = 9+补码(10-2) = 17  = 7(10分为溢出丢弃) ; -2的补码为8

4)个人理解对于十进制

反码: 一个数的原码+这个数的反码+1=一个数的进位值(十进制  3的反码是6,进位值为10,则3+6+1=10,    (3+7=进位值(10), 7 是3的同余数))

个人理解补码:溢出值的最大值-对应的值 -> 最终使结果相加以后会有溢出-> 使得加法最终得到减法的结果

反码只是计算补码的一个过渡

四、二进制左移和右移运算

在机器中,数的二进制码都是其补码。

1)负数的右移:需要保持数为负数,所以操作是对负数的二进制位左边补1。如果一直右移,最终会变成-1,即(-1)>>1是-1。

2) 负数的左移:和整数左移一样,在负数的二进制位右边补0,一个数在左移的过程中会有正有负的情况,所以切记负数左移不会特殊处理符号位。如果一直左移,最终会变成0。

3)正数左移和右移两边位数补0即可

4)>>>无符号右移:左边补0,无论正负

五、Java中的右移和无符号右移测试

例子: 

public static void test123(){
        System.out.println(  " 正数右移测试 ");
        int k=10;
        String  k0 = Integer.toBinaryString(k ) ;
        int k1 = k>>1;
        int k2 = k>>>1 ;
        System.out.println( k0 +" == "+k );
        formatPrint(k,k0.length()  );
        formatPrint(k1,k0.length()  );
        formatPrint( k2,k0.length());
        
        
        System.out.println("====下面是负数右移测试============");
        //
        /**
         * -10 变成二进制后是使用补码表示的
         * 源码: 11010
         * 反码: 10101
         * 补码:10110
         * 正数是32位所以打印出来为:11111111111111111111111111110110
         */
        int j=-10;
        int   binLen = Integer.toBinaryString( j ).length();
        int j1 = j>>2;
        int j2 = j>>>2 ;
        formatPrint( j ,   binLen );
        formatPrint( j1 , binLen  );
        formatPrint( j2, binLen );
//        System.out.println(Integer.toBinaryString( j ) );

    }


    public static  void formatPrint( int val , int len ){
        System.out.println( StringUtils.leftPad( Integer.toBinaryString(val ) , len  , "0") +" == "+ val );
    }

  结果:

正数右移测试
1010 == 10
1010 == 10
0101 == 5
0101 == 5
====下面是负数右移测试============
11111111111111111111111111110110 == -10
11111111111111111111111111111101 == -3
00111111111111111111111111111101 == 1073741821

原文地址:https://www.jb51.cc/wenti/3284982.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐