数据存储
1 byte = 8 bit
原码
计算机进行存储计算必须要保存数值,原码就是一个字符的二进制序列,例如 1 的源码就是 0000 0001
。但是我们还要计算负数,怎么表达一个负数呢?用存储单元的第一位表示符号位,最高位为 1 时表示负数,最高位为 0 时表示正数,其余位为数值位。
反码
如果通过原码进行计算的话,你会发现原码存在一个严重的问题,+1(10000001) 和 -1(00000001) 的值为 -2(1000 0010)。这样显然是不行的。对于人类而言,分辨符号位是非常简单的,然后根据后面的绝对值进行加减并得出结果。对于计算机来说将符号位分开处理有点儿复杂了,如果电路也设计的非常复杂,那么最后计算机的效率就会变得很慢。所以如何让符号参与运算,让其形成一个完整的逻辑?
由此,引入了反码:正数的反码即正数本身,负数的反码除符号位外按位取反。
正数原码 | 原码二进制 | 负数原码 | 负数原码二进制 | 负数反码 |
---|---|---|---|---|
+0 | 0000 0000 | -0 | 1000 0000 | 1111 |
+1 | 0000 0001 | -1 | 1000 0001 | 1111 |
+2 | 0000 0010 | -2 | 1000 0010 | 1101 |
通过这个设计,正负数相加的和都是 1111
,即 -0。
补码
反码解决了带符号位的运算问题,但是还有一个问题没有解决:+0 和 -0.它们在数学上是没有区别的,但是占了两个编码,可用范围将减 1;对电路设计人员来说,要检查值是否为 +0,然后检查值是否为 -0。为了解决这个问题,引入了补码。引入补码之后 -0 取补码后跟 0 是一致的,解决了两个 0 的问题。
正数原码 | 原码二进制 | 负数原码 | 负数原码二进制 | 负数反码 | 负数补码 |
---|---|---|---|---|---|
+0 | 0000 0000 | -0 | 1000 0000 | 1111 1111 | 0000 0000 |
+1 | 0000 0001 | -1 | 1000 0001 | 1111 1110 | 1111 1111 |
+2 | 0000 0010 | -2 | 1000 0010 | 1111 1101 | 1111 1110 |
补码:正数和 0 的补码不变,负数的补码是对应的正数按位取反再加 1(即负数的补码的其反码 +1)。
需要注意的是,在计算机中,所有的数字都是以补码形式进行存储和运算的,包括正数和负数。在进行加减运算时,只需要将两个数的补码按位进行计算,就可以得到正确的结果,而无需进行转换。这种方式可以大大简化计算机中的运算,并且可以提高运算的速度。
例如,对于数字 5 和 -5 进行加法运算,可以将两个数的补码按位计算得到:0000 0101(5) 1111 1011(-5)
进制
十六进制
我们知道,计算机只认识二进制,也只能对二进制进行操作。但是在数据的传输中却是使用的十六进制。这是为什么呢?
数学计算上,16 正好是 2 的四次幂,计算机中则可以使用位运算,十六进制与二进制转换快速;另外十六进制的一个字节为 4 bit。正常情况下,一个字节是 8 bit,那么 2 个十六进制正好组成一个字节。为什么一个字节有 8 bit呢?这是 历史的原因 了。