一、原码反码补码定义
原码:是最简单的机器数表示法。用最高位表示符号位,‘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 举报,一经查实,本站将立刻删除。