Fork me on GitHub

计算机中的整数(原码、反码、补码)

  系统中所有的信息——包括磁盘文件、存储器中的程序存储器中存放的用户数据以及网上落上传送的数据,都是由一串位表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。比如,在不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。

  计算机中的整数可以分为无符号整数和有符号整数两种类型。无符号整数不存在正负之分,在计算机中以其二进制真值的形式存放。而有符号整数由于有正负数的区分,表示相对复杂。

  计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,他们的最高有效位就是符号位,都是用0表示“正”,用1表示“负”;而数值位,三种表示方法各不相同。

 

原码(Sign-Magnitude):

  原码就是符号位加上真值的绝对值,即用第一位表示符号, 其余位表示值。比如如果是8位二进制:

[+1] = 0000 0001

[- 1] = 1000 0001

  因为第一位是符号位,所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

  即

[-127 , 127]

  原码是人脑最容易理解和计算的表示方式。

 

反码(Ones' Complement):

  正数的反码是其本身;负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

[+1] = [00000001] = [00000001]

[ -1] = [10000001] = [11111110]

  可见如果一个反码表示的是负数,人脑无法直观的看出来它的数值,通常要将其转换成原码再计算。

 

补码(Two's complement)

  正数的补码就是其原码本身;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1 (即在反码的基础上+1)。

[+1] = [00000001] = [00000001] = [00000001]

[ -1] = [10000001] = [11111110] = [11111111]

  对于负数, 补码表示方式也是人脑无法直观看出其数值的,通常也需要转换成原码在计算其数值。

 

为什么最终使用补码?

  计算机的设计者为了简化运算器的结构、提高运算速度,将减法、乘法、除法都转化为了加法运算。根据运算法则减去一个正数等于加上一个负数,但是计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂,于是人们想出了将符号位也参与运算的方法。

  原码反码有一个奇怪的属性,那就是对于数字0有两种不同的编码方式。这两种表示方法把00..00都解释为+0;而值-0在原码中表示为10..00,在反码中表示为11..11。显然给0加上正负号都是没有意义的,而且影响了符号位参与运算的目标。补码解决了这个问题,0在补码中只有一种表示,那就是所有位都是0。

  使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

posted on 2016-04-18 21:47  地精的贪婪  阅读(1032)  评论(0编辑  收藏  举报