计算机底层为什么要用补码,而不用原码或反码?
概念
比特与字节
计算机是依二进制的方式进行存储的,最小的存储单元是“比特(bit)“,或者称作“位“,这是二进制的概念,相对于10进制的就是个十百千万这样的位。
但计算机在存储的时候是按8个比特位“为一个“字节(byte)“进行存储的,即1byte = 8bit。
1个比特可以表示两种信息,8个比特就可以表示可以存储28种信息,即256种不同的信息。所以用一个字节来表示整数的话就是0-255,。这个区间数字的应用也非常的多,举一个最常见的例子:RGB颜色的值,就是0-255。还有一个例子就是MySQL数据库的TINYINT 型的字段如果不设置UNSIGNED类型,只能存储-128到127的整数。也就是256种不同的结果,同时一个TINYINT型数据只占用一个字节。 这也就是为什么MySQL初学者疑惑的数据占用的字节跟自己想得不一样问题。
二进制的8个长度误区,2进制为什么用8位表示?
网友的解释是:
计算机中只要一个字节就可以存放ASCII编码,就是所有的数字、大小写字母和一些特殊字符(总共刚好255个)。所以在计算机中对用户来说有意义的单位就是字节。
个人的想法是:
8个长度的2进制数据,最多表示256种情况,很有局限性,257种情况下,8位就完不成了,何况世界那么大,256太小了。所以二进制跟用8位表示没有直接关系,简单的8位它也表示不完。
8个长度仅仅表示257以内或-128到127数据的习惯表示方法。但凑够8个固定长度为一个字节,到是保持了小数据的占用空间的一致性,放到一个字节里就是8位。这东西了解就行,不用深究,公司上班不会问你这些。
原码:
0的二进制是0,1的二进制是1,2的二进制是10,3的二进制是11。
习惯8位长度的表现形式。所以写法就是:0也可以表示成00000000,以此类推,11可以表示成00000011。长度不够,用零来凑。
需要注意的是:整数的正负属性使用字节的最高位来区分,也就是从左数第一个数字来表示正负,0为正,1为负。
举个栗子:
10进制的3,二进制就是00000011;
10进制的-3,二进制就是10000011;
例子的核心的数据就是开头的0或1,和结尾的11,。中间用0填充使其一共凑够8个长度。就是说分两块:左边最高位代表正负,结尾非0开始有用的是绝对值,中间不够用0填充。
这种写法叫做原码。
反码:
反码的意思就是除符号位(可以理解成左边第一个字符)不变外,其余按位取反,这种方式对负数生效。对于正数,正数的反码可以理解为和原码相同,也就是不进行除符号位外的取反操作。
举个例子:
已经知道1的原码可以写成00000001,反码就是00000001
同样的-2的原码是10000010,反码就是11111101
补码:
正数的补码可以理解为和原码相同,负数的补码可以理解成,反码+1
举个例子:
已经知道1的原码可以写成00000001,补码就是00000001
同样的-2的原码是10000010,补码就是11111101 + 1 = 11111110
小结:
正数的反码和补码与原码是没有区别的。所以反码和补码是针对负数的。
计算机底层为什么要用补码,而不用原码或反码?
回答之前需要了解
计算机是不能直接做减法运算的,因为普通电脑硬件中没有减法器,不需要额外的增加硬件电路制造难度,减法器无需存在。但可以优雅的转换成减法
如何计算?【10 - 7】可以转换成【10 + (-7)】,就这么简单。计算机的脑袋没有减法概念,不代表没有负数的概念。
计算【1 - 1 = 0】,若用原码计算:
转成原码后进行计算:
00000001 + 10000001 = 10000010
10000010 是-2,计算错误。
则:原码不能做计算。
计算【1 - 1 = 0】,若用反码计算:
转成反码后进行计算:
00000001 + 11111110 = 11111111
此时的8个1是反码,转成原码,就是10000000,也就是 - 0
-0和0也算正确。
但是又会出来一个问题:
0就有两种表示方法:10000000或00000000
由于计算机是严谨的学术,并且学术也是严谨的,在现实生活中-0和0区别不大,但是在计算机中被认为是不合理的。
则:反码不适合做计算。
计算【1 - 1 = 0】,若用补码计算:
转成部码后进行计算:
00000001 + 11111111 = 00000000
8个0是0,计算正确,也解决了反码带来的问题。
则:用补码计算最好。
为什么00000001 + 11111111 = 00000000?
此时可要想好:
00000001 是1,没毛病。
11111111可不是255,它是-1的补码。
所以结果不会是100000000,也就不是256,这是补码的规则,不是逢二进一的规则。
补码满足以下计算规则:
⑴如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
⑵如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。