目录
在开始前,先问问大家一个问题,为什么一个字节的取值范围是-128~127呢?
1.原码:
原码是十进制数据的二进制表现形式,最左边是符号为,0表示正,1表示负。
比如56的二进制为0011100(第一个0为符号位,0111000为数据)
其中一个数字0或1表示一个比特位(bit),而一个字节为八个比特位,即0011 1000为1个字节(8个比特位)
按照定义,原码最大值与最小值分别为0111 1111(对应十进制数127)和1111 1111(-127)
一般来说原码对正数之间的计算没有什么问题,但在进行负数计算时出现弊端了。
注意:二进制的计算关键点是逢2进1,比如0000 0001+1=0000 0010
比如,
二进制:1000 0000->十进制:-0(即0)
加一后,对应十进制数应该为1对吧,但实际上是-1
二进制:1000 0001->十进制:-1(本来应为1)
依次类推,实际上都是取到相反数
为什么这样呢?
因为最左项的符号位,使得相加数均为负数,由此为解决这个问题,我们引出了反码的概念。
2.反码:
反码:为解决原码在负数计算失效的情况而出现的
计算规则:
·负数的反码,符号位不变,数据取反,即0变1,1变0
·正数的反码为其本身(即什么都不用变)
举个栗子:
十进制:-56->原码:1011 1000
其反码为:
十进制:-56->反码:1100 0111
则+1后为1100 1000,其对应十进制数为-55,结果与我们想要的一样。
那此时可能就有人问了,这个反码是否跟上面原码一样有什么缺点呢?
答案是,有,它的缺点是在进行跨0计算时会与正确的结果存在一个误差。
比如:
-5的二进制数是1111 1010,
6的二进制数是0000 0110,
二者则相加等于0000 0000(只取8位)转成十进制是0
而与我们想得到的结果(1)相差一个1。
那么为什么会出现这样的情况呢?
因为在反码中,十进制的0的二进制有两种表现形式,因此我们在进行跨0运算时总是多一位。
那么我们接下来主要解决的就是将两种表现形式变成一种,这样就可以实现跨0 运算了
由此,我们引出了补码的概念。
3.补码:
补码,与反码相比是错开一位的,比如(反码中对应-0)1111 1111改为对应-1,1111 1110改为对应-2,以此类推,最终实现了0对应一种二进制表现形式。
另外,这里还有一个小细节,就是-127的补码对应为1000 0001,这样就会空出一位,就是1000 0000,不过这也好理解,因为补码跟反码、原码是错开一位的,因此最后会多出一位,即-128无对应的原码和反码,不过由于计算机的数据存储与运算是通过补码进行的,所以并不影响计算机运行与工作。
由此我们就能更好的理解为什么一个字节的取值范围是-128~127了。