一.机器数和真值
- 机器数
-
一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。
- eg. 十进制7机器数就是0000 0111,十进制-7机器数就是1000 0111。
-
- 真值
- 将带符号位的机器数对应的真正数值称为机器数的真值。就是上面例子里的7和-7。
- 因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 1000 0111,其最高位1代表负,其真正数值是 -7 而不是形式值135(1000 0011转换成十进制等于135)。
二.原码 反码 补码的基本概念和计算方法
- 原码
-
原码就是符号位加上真值的绝对值(就是机器数), 即用第一位表示符号, 其余位表示值。
[7]=[0000 0111]原 [-7]=[1000 0111]原
-
原码是人脑最容易理解和计算的表示方式。
-
- 反码
- 正数的反码是其本身。
[7]=[0000 0111]原=[0000 0111]反
- 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
[-7]=[1000 0111]原=[1111 1000]反
- 正数的反码是其本身。
- 补码
- 正数的补码就是其本身。
[7]=[0000 0111]原=[0000 0111]补
- 负数的补码是在反码的基础上+1。
[-7]=[1000 0111]原=[1111 1001]补
- 对于负数, 补码表示方式是人脑无法直观看出其数值的。
- 正数的补码就是其本身。
三.为何要使用原码 反码 补码
- 两个数做加减的时候,人脑很自然的会区分正负数并做相应运算。但计算机里面,只有加法器,没有减法器,所有的减法运算,都必须用加法进行,而且是保留符号位的加法运算。于是产生了反码 补码。
- 先看看三种运算:
- 原码运算。如果用原码表示,让符号位也参与计算,显然对于减法来说,结果是不正确的。这也就是为何计算机内部不使用原码表示一个数。
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [1000 0010]原 = -2
- 反码运算。发现用反码计算减法,结果的真值部分是正确的。而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的,但是0带符号是没有任何意义的。而且会有[0000 0000]原 和[1000 0000]原 两个编码表示0。
1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
- 补码运算。解决了0的符号。
1 - 1 = 1 + (-1) = [0000 0001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]原 = 0
- 原码运算。如果用原码表示,让符号位也参与计算,显然对于减法来说,结果是不正确的。这也就是为何计算机内部不使用原码表示一个数。
四.-128的补码问题
- 假设机器能处理的位数为8,即一个字节,如果不考虑最高位用做符号位的情况,8位可以表示的数据区间是0000 0000 - 1111 1111,即0-255,共256个数据。
- 如果考虑最高位用做符号位的情况,8位可以表示的数据区间是1111 1111 -1000 0000和0000 0000 - 0111 1111,即-127 - -0和+0 - 127,共256个数据。
- 在原码和反码中,数据的区间为-127 - -0和+0 - 127;在补码里面用-128代替了原码和反码里的-0,补码范围变成了-128 - 0 - 127。
- 补码里面用-128代替了原码和反码里的-0产生了什么
原码和反码里面:[-0] = [1000 0000]原 = [1111 1111]反 = [1000 0000]补 补码里面:-128代替上面的[-0]==========>[-128] = [1000 0000]补,但-128并没有原码和反码表示。
-
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补 = -128
五.补码的设计目的
- 使符号位能与有效值部分一起参加运算,从而简化运算规则。
- 使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。
六.补码的原理分析
见参考文章http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
同时感谢参考文章。