前言:可能需要一些十进制与二进制转换和二进制进位知识
后文皆以字节(byte)为例
原码
第一位作为符号位,0表正数,1表负数
0000 0000//0
1000 0000//-0
0000 0001//1
1000 0001//-1
0111 1111//得到 byte 最大值127
反码
原码负数计算问题
1000 1010 + 0000 0001 = 1000 1011//-10 + 1 = -11
为解决原码计算负数的问题,反码出现
原码转反码:符号位不变,其余按位取反
1000 1010//原码-10
1111 0101//反码-10
使用反码表示负数计算
1111 0101 + 0000 0001 = 1111 0110//-10 + 1 = -9
正数的原码=反码=补码
补码
反码的0有两种表示方式,导致跨0运算有误差
0000 0000//0
1111 1111//-0
1111 1110 + 0000 0010 = 0000 0000//-1 + 2 = 0
于是,令其错位
使用补码计算
1111 1111 + 0000 0010 = 0000 0001//-1 +2 =1
至此,可完美运算两数相加
同时,-127反码向下错位得到-128
1000 0000//反码-127,补码-128
计算机数据存储和计算都使用补码
所以,byte取值为-128到127
从原码直接到补码
不妨设负数的二进制为未知数
0000 0001 + ???? ???? = 0000 0000//1 + (-1) = 0
0000 0010 + ???? ???? = 0000 0000//2 + (-2) = 0
0000 0011 + ???? ???? = 0000 0000//3 + (-3) = 0
-1 = 1111 1111
-2 = 1111 1110
-3 = 1111 1101
实际上,这样的思路更合理和易理解
最后奉上负数的补码计算方法:
1. 取负数绝对值的二进制
2. 按位取反
3. 再加1
例如:
1. 计算-7绝对值7的二进制0000 0111
2. 按位取反1111 1000
3. 再加1得-7的补码1111 1001
补充
- 补码使得在设计cpu硬件电路的时候,只需要设计加法器电路而无需设计减法器电路,极大简化了电路设计
- 如果你在一个byte变量上执行127 + 1,结果会溢出,得到-128
- 固定宽度的整数的范围可以被看作是一个环状结构,在某些时候能够加以运用