人类为什么使用 10 进制呢?据说是因为人类有 10 根手指。电脑使用二进制,原因大概是二相的电器元件容易制造。
不管是人类的 10 进制还是电脑的 2 进制,归根结底都是为了表达数字。数字是独立于进制的,不管进制是什么,数字总还是那个数字。
很久很久以前,人类对于10以上的数字是没有概念的。大家都是就着自己的手指头数数,数到10就达到了极限。可是有个天才发明了一种做法,让人类的数数能力获得了质的飞升。他是这么做的:数完了自己的手指头,就在自己的身前放一颗小石子。然后让自己的手指头“清零”,继续数数。数完所有东西后,再回来数数小石子。于是,人类发明了二位数。 二位数发明之后,三位数也不远了。
人类历史上不仅出现了 10 进制,还出现了 20 进制。想必,发明了两位数的天才出现之前,出现过另一个天才,想到了用脚趾头数数。
二进制表达数字也和 10 进制类似,你把计算机想象成一个只有两个手指的怪人,计算机数到 2 ,就在自己身前放一颗小石子。
下图中,左边是十进制,右边是二进制。二位的两进制只能表达那么多个数。
1 1
2 10
3 11
就像老师经常说的,十进制是 逢十进一 ,二进制是 逢二进一 。只要照着这个规则,我们可以将上面的表一直对应下去。
根据进制表达数的本质,我们可以写下如下的 python 代码,对任意进制的数字求值。
二进制表达负数。人类用-/+来表达正负的概念,二进制中用最高位 0 / 1 来表达正负的概念。 0 就是正数, 1 就是负数。
在现代计算机中,负数是用补码表示的。
比如, 5 的二进制表示形式是 101 。如果字长是 8 ,就是 00000101 。表示负数的时候,只需将最高位逆转。那么二进制的 -5 可以用 10000101 来表示。这本来没什么问题,可是考虑到计算部件的成本,人们用了另外一种表示方式。
如果我们用上面的方法表示正负数,在计算机中,加法电路和减法电路就是两套不同的电路。 但人们希望,加法和减法可用统一用同一套电路(加法电路),以便减少成本。令人吃惊的是,这竟然可以通过编码来做到。
至少,相反数相加必须得 0 。 5 和什么数相加能够得 0 呢?那么这个数不就是 -5 了?
00000101
xxxxxxxx
--------
00000000
显然这个等式是不可能成立的。我们让结果得到一个进位,一切就变得合理了。
00000101
xxxxxxxx
--------
100000000
计算机在做加法的时候,如果进位超出了范围,会被舍去。接下来,求出 x 是小学生都会做的题目了。一个巧妙的思路是这样的,先求出下式中的 y ,然后让 y 加 1 ,即得 x 。
00000101
yyyyyyyy
--------
11111111
求y的过程非常简单,正是 取反操作 。取反操作就是 0 变 1 , 1 变 0 。
这就是为什么补码要取反加一的由来。
这也可以解释为什么补码是自反的。所谓自反就是补码再次取反加一就得到原码,因为从 5 找 -5 和从 -5 找 5 是一个道理。
补码 之所以叫做补码,就是因为它和原码相加,会让结果归零。它和原码天生是一对。