原码:

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

[+1]原 = 0000 0001

[-1]原 = 1000 0001

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

[1111 1111 , 0111 1111],即:

[-127 , 127]

例如5和-5的原码:

00000000 00000000 00000000 00000101 //为5

10000000 00000000 00000000 00000101 //为-5

计算机中并没有减运算,减运算实际是加一个负数的运算,这也就是为什么正数之间的加运算会比减运算快的原因,减运算需要做更多的处理来让计算机解读成能理解的加运算,例如5-5计算机要处理成5+(-5),原码在高位用0和1解决了区分正负的问题,但是又引来的新的问题,因为我们都知道5+(-5)是等于0的,但是我们来看看原码之间的运算结果:

00000000 00000000 00000000 00000101+10000000 00000000 00000000 00000101

=10000000 00000000 00000000 00001010

10000000 00000000 00000000 00001010的原码并不是我们期待的0,而是-10,5+(-5)=-10这肯定不是我们要的结果,不仅如此原码正数高位为0,所有负数高位为1,这个时候会出现两个0的情况,一个为正0,一个为负0,这显然不太合理,0是没有正负的,为了解决第一个问题后来又引入了一个新的概念,那就是反码。

反码:

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

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

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

一个正数和自身对应的负数的反码互为补数,因此减去该正数和加上该正数对应的负数的反码结果是一样的。

例如5和-5

00000000 00000000 00000000 00000101 //正数5和上面原码及普通二进制一样的表示

11111111 11111111 11111111 11111010 //-5的反码是5的二进制(或者说原码、反码都可以,因为都一样)0和1的反转

00000000 00000000 00000000 00000101+11111111 11111111 11111111 11111010 

=11111111 11111111 11111111 11111111

这里的11111111 11111111 11111111 11111111是00000000 00000000 00000000 00000000的反码,所以是-0,这样反码的出现就解决了正负数字的运算问题,但是还存在一个问题,就是上面的0是两个,一个为正0,全为0,一个为负0,全为1。为了解决这个问题,又引入了补码的概念。

补码:

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

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

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

5的反码:00000000 00000000 00000000 00000101

5的补码:00000000 00000000 00000000 00000101

 

-5的反码:11111111 11111111 11111111 11111010

-5的补码:11111111 11111111 11111111 11111011 //就是在-5的反码基础上+1

 

00000000 00000000 00000000 00000101+11111111 11111111 11111111 11111011 

=00000000 00000000 00000000 00000000  //5的补码+(-5的补码)=0且0没有正负号

总结:二进制不能表示负数,而原码虽然能表示负数,但无法进行正负数运算及两个0的问题,反码解决正负数运算的问题然后还保留着两个0的问题,只有补码完美解决了正负数运算问题同时还解决了两个不同符号的0的问题