大家知道了计算机可以有三种编码方式表示一个数.对于正数因为三种编码方式的结果都相同:
[+1]=[00000001]原=[00000001]反=[00000001]补
所以不需要过多解释.但是对于负数:
[-1]=[10000001]原=[11111110]反=[11111111]补
可见原码,反码和补码是完全不同的.既然原码才是被人脑直接识别并用于计算表示方式,为何还会
有反码和补码呢?
首先,因为人脑可以知道第一位是符号位,在计算的时候大家会根据符号位,选择对真值区域的加减.
(真值的概念在本文最开头).但是对于计算机,加减乘数已经是最基础的运算,要设计的尽量简单.
计算机辨别”符号位”显然会让计算机的基础电路设计变得十分复杂!于是人们想出了将符号位也参与
运算的方法.大家知道,根据运算法则减去一个正数等于加上一个负数,即:1-1=1+(-1)=0,
所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了.
于是人们开始探索将符号位参与运算,并且只保留加法的方法.首先来看原码:
计算十进制的表达式:1-1=0
1-1=1+(-1)=[00000001]原+[10000001]原=[10000010]原=-2
如果用原码表示,让符号位也参与计算,显然对于减法来说,结果是不正确的.这也就是为何计算机内
部不使用原码表示一个数.
为了解决原码做减法的问题,出现了反码:
计算十进制的表达式:1-1=0
1-1=1+(-1)=[00000001]原+[10000001]原=[00000001]反+[11111110]反=[1111
1111]反=[10000000]原=-0
发现用反码计算减法,结果的真值部分是正确的.而唯一的问题其实就出现在”0″这个特殊的数值上.
虽然人们理解上+0和-0是一样的,但是0带符号是没有任何意义的.而且会有[00000000]原和[1000
0000]原两个编码表示0.
于是补码的出现,解决了0的符号以及两个编码的问题:
1-1=1+(-1)=[00000001]原+[10000001]原=[00000001]补+[11111111]补=[0000
0000]补=[00000000]原
这样0用[00000000]表示,而以前出现问题的-0则不存在了.而且可以用[10000000]表示-128:
(-1)+(-127)=[10000001]原+[11111111]原=[11111111]补+[10000001]补=[1000
0000]补
-1-127的结果应该是-128,在用补码运算的结果中,[10000000]补就是-128.但是注意因为实际上
是使用以前的-0的补码来表示-128,所以-128并没有原码和反码表示.(对-128的补码表示[10000000]
补算出来的原码是[00000000]原,这是不正确的)
使用补码,不仅仅修复了0的符号以及存在两个编码的问题,而且还能够多表示一个最低数.这就是为
什么8位二进制,使用原码或反码表示的范围为[-127,+127],而使用补码表示的范围为[-128,127].
因为机器使用补码,所以对于编程中常用到的32位int类型,可以表示范围是:[-231,231-1]因为第
一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.