写在前边的话
记得第一次接触机器数的编码方式还是在大一的计算机导论课上,当时看到书上写的机器数、真值、原码、反码、补码、移码这几个词的时候,看的我头皮发麻,心里想着,搞这么多码干啥呀 (╯' - ')╯︵ ┻━┻ 。
funny-王宝强-写的这是啥.jpg后来由于某些不可抗拒的因素,将这些知识归还给了老师。想来些许惭愧,于是决定重新温习一遍,结合网上的学习资料,简单做个学习手记,希望能对后来的同学能有所帮助。o( ̄︶ ̄)o
come on,来跟原反补码做个了断吧!
这些码都是怎么来的?
我们知道,计算机是由0和1的二进制数组成,为了表示负数的概念,比方说想表示“欠马爸爸多少钱”,人们发明了原码这么个词。
概念:把数值左边第一位腾出位子,来存放符号,用0表示正数,1表示负数。
原码的形式,我们人看倒是方便了,却苦了计算机。不信你看:
human : (+1)+(-1)= 0;
but...
computer : 0001B + 1001B = 1010B (-2)
human : (╯' - ')╯︵ ┻━┻
为了解决“正负相加不等于0”的问题,在“原码”的基础上,人们又发明了“反码”
概念:“反码”表示方式是用来处理负数的,符号位不变,其余位置取反
我们看到,当“原码”变成“反码”时,完美的解决了“正负相加不等于0”的问题
过去的(+1)和(-1)相加,
变成了 [0001]反 + [1110]反 = [1111]反,
刚好反码表示方式中,[1111]反 表示 “-0"。
我们发现,使用反码,还是会有两个零存在,+0 和 -0。(带符号的零完全没有意义)所以我们希望只有一个0,所以人们又发明了"补码"。
概念:“补码”同样是针对"负数"做处理的,在原来"反码"的基础上,补充一个新的代码,(+1)
++我们的目标是,没有蛀牙(-0)++
我们来看,对于“反码”中的“-0”,即1111B,再补上一个1之后,变成了10000B,因为要丢掉数值最高位,剩下的就是0000B,大家发现没有,得出来的结果是不是左边那个正数0呢,这样就解决了+0和-0同时存在的问题啦。同样举个例子:
3 + (-3)
[0011]补 + [1101]补 = 10000
丢掉最高位,就是 0000B
有失必有得,根据能量守恒定律,我们失去了(-0),却收获了(-8),
即[1000]补,我们惊喜的发现,相较于原码和反码,补码可以最低位可以多表示一位。
我们可以来看下面这个例子:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原
= [1111 1111]补 + [1000 0001]补 = [1000 0000]补
-1-127的结果应该是-128, 在用补码运算的结果中,
[1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128,
所以-128并没有原码和反码表示.
为什么不直接用减法?
相信不少小伙伴可能会发出这样的疑问,为啥不干脆直接 1 - 1 得了,搞得这么麻烦干嘛?
原因其实很简单,因为计算机笨呀 (ಥ_ಥ)
我们人脑可以知道第一位是符号位,计算的时候我们会根据符号位,选择对真值区域(可以理解成绝对值)做加减,而要让计算机识别“符号位”,显然会让计算机的基础电路设计的十分复杂,于是乎,人们想出了,将符号位也参数运算的方法,我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.
写在后边的话
通过上面的介绍,相信大家能够明白,
- 首先,计算机为了保存负数,通过不断改进方案,最终选择了最好的“补码”方案,“反码”不过是这一推演过程的中间产物。
- 其次,反码和补码都是用来处理负数的,所以正数的反码就是其本身,千万别把正数也取反了
- 最后,8位二进制,使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].那么,不妨思考一下,32位的int类型,可表示的范围应该是多少呢?
网友评论