不知道大家有没有想过计算机是如何存储负数的呢?
众所周知计算机里面存储数据都是用二进制来存储的,那么怎么用二进制来表示负数呢?
在设计计算机的时候,设计的人觉得减法很麻烦,就想用加法代替减法,那么怎么替代呢?请接下来往下看:
这里我们需要介绍三种码
分别是 健康码,沙琪玛,饿了么扫个码
分别是 :
源码,反码,补码。
那么这三个码分别是什么呢?
我们来举个栗子:
我们以 6 来作为例子
源码
6的二进制为多少呢?
很明显
6的二进制为
0000 0000 0000 0000 0000 0000 0000 0110
那么我们就说6的源码为
0000 0000 0000 0000 0000 0000 0000 0110
反码
什么叫做反码呢?
答案就是:将源码的所有的0变为1,1变为0
所以6的反码就是
1111 1111 1111 1111 1111 1111 1111 1001
补码
什么叫做补码呢?
答案就是:将反码加上1就变为了补码
那么6的补码是多少呢?
很明显,补码为
1111 1111 1111 1111 1111 1111 1111 1010
我们将补码表示该数的负数
解释
那么我们来解释一下为什么能用补码表示负数。
我们依旧以6来举例子
众所周知
6+(-6)=0
上面也介绍了
6的二进制为 0000 0000 0000 0000 0000 0000 0000 0110
0的二进制为 0000 0000 0000 0000 0000 0000 0000 0000
我们假设-6的二进制为x
则有
0000 0000 0000 0000 0000 0000 0000 0110 + x =0000 0000 0000 0000 0000 0000 0000 0000
这时候我们就可以得到
x=1111 1111 1111 1111 1111 1111 1111 1010
有的同学就在想这是怎么得到的呢?
1111 1111 1111 1111 1111 1111 1111 1010 0000 0000 0000 0000 0000 0000 0000 0110 ----------------------------------------------- 10000 0000 0000 0000 0000 0000 0000 0000
可是一个int最多只能存储三十二位,而对于二十三位的二进制,只能保存后三十二位,最高的一位无法保存,也就是我们所谓的溢出。
那么和上面的三种码有什么关系呢?
上面的原理我们还可以拆分一下,可以变成如下
1:先将6的二进制加上一个数之后,使它的二进制变成全1,那么一个数加上什么能使它的二进制变成全1呢,很明显,就是我们上面所说的反码
2:然后加上1,就利用溢出,就可以实现归零了。
所以我们表示一个负数,只需要用它正数的反码即可。
这里还需要补充的是:
我们都知道int在64位机器中占4个字节,一个字节占8个比特位,所以一个int占32个比特位,理论上最大值应该是
2
32
2^{32}
232,但是因为要存储负数,所以我们需要有一个比特位来分辨正负数。也就是
−
2
31
≤
-2^{31} \leq
−231≤int
≤
\leq
≤
2
31
−
1
2^{31}-1
231−1。
我们仔细观察一下,int的正数的最大值为
2
31
−
1
2^{31}-1
231−1,而
( 2 31 − 1 2^{31}-1 231−1) 2 _2 2=0111 1111 1111 1111 1111 1111 1111 1111
我们可以观察到:int的正数的最大值,也有一位为0,也就是第三十二位一直为0,如果要表示负数,则会将该数先取反再+1,如果对最高位进行取反再+1的话,最高位则会为1,那么我们将会得出一个结论:
最高位(第三十二位)为0的时候:表示的数为正数
最高位(第三十二位)为1的时候:表示的数为负数
但是这里有一个算不上特例的特例:
也就是0,我们知道
( 0 ) 2 (0)_2 (0)2为0000 0000 0000 0000 0000 0000 0000 0000
而取反之后为
1111 1111 1111 1111 1111 1111 1111 1111
接着+1之后会变成
0001 0000 0000 0000 0000 0000 0000 0000 0000
而因为溢出,会导致int取最后三十二位,也就是
0000 0000 0000 0000 0000 0000 0000 0000
有人会说这样取反+1之后,最高位不为1呀,可是这个数为0,最高位不论是1或者是0,都是一样的。
总结
至此本篇完毕。