转载:《编码的奥秘》 第八章
1 0对我们来说是一个非常重要的数字。 1 0是我们大多数人拥有的手指或脚趾的数目,我们当然希望所有人的手指脚趾都是 1 0个。因为我们的手非常适合数数,因而我们人类已经适应了以 1 0为基础的数字系统:
前面数章已经提到过,通常使用的数字系统称为以 1 0为基础的数字系统或十进制。这个数字系统对我们来说非常自然,因而我们很难想像出还有其他的数字系统。事实上,当我们看到数字 1 0的时候,不由自主地就会认为这个数是指下面这么多只鸭子:
但是,数字 1 0是指这么多只鸭子的唯一理由是因为这么多只鸭子与我们的手指数目相同。如果人类不是有那么多只手指,我们数数的方式就会有所不同,数字 1 0就可能代表别的东西了。同样是数字 1 0,可以指这么多只鸭子:
或这么多只鸭子:
甚至可以是这么多只鸭子:
当我们明白了 1 0可以指只有两只鸭子的时候,也就可以解释开关、电线、灯泡、继电器(或干脆就叫计算机)是怎样表示数字的了。
如果人类像卡通人物那样,每只手上只有 4个手指会怎样呢?我们可能永远都不会想到要发明一种以 1 0为基础的数字系统的问题, 取而代之的是我们可能会认为数字系统基于 8是正常、自然、合理、必然的,是毫无疑问的,是非常合适的。这时,就不能称之为十进制了,得将它称作为以 8为基础的数字系统或八进制。
如果数字系统是以 8为基础组织起来的,就不需要这样的一个符号:
把这个符号拿给任何一个卡通人物看,都会有同样的反应: “那是什么?它是干什么用的?”如果再仔细想一会儿的话,你会发现连这样的一个字符也不需要:
在十进制数字系统中,没有专门用来表示 1 0的符号,所在在八进制数字系统中,也没有专门用来表示 1 0的符号。
在十进制数字系统中数数的方式是 0、 1 、 2、 3 、 4、 5、 6、 7、 8、 9,然后是 1 0。在八进制数字系统中数数的方式是 0、 1 、 2、 3、 4、 5、 6、 7,然后是什么呢?我们已经没有符号可用了,唯一的一个有意义的可用符号是 1 0,的确是那样。在八进制数中, 7之后紧接着的数字是1 0,但是 1 0并不是指人类的手指那么多的数目。在八进制数中, 1 0指的是卡通人物手指的数目:
继续数脚趾头:
使用非十进制的数字系统时,将数字“ 1 0”读作“幺零”可以避免一些混淆。同样, “ 1 3”可以读作“幺三”, “ 2 0”可以读作“二零”。要想真正避免混淆,可以将“ 2 0”读作“八进制二零”或“基于 8的数二零”。
即使没有手指和脚趾帮忙,我们仍能够将八进制数继续数下去。除了要跳过那些含有 8或9的数字以外,它基本上和数十进制的数是一样的。当然,相同的数字代表的数量是不同的:
0、 1 、 2、 3、 4、 5、 6、 7、 1 0、 11、 1 2、 1 3、 1 4、 1 5、 1 6、 1 7、
2 0、 2 1 、 2 2、 2 3、 2 4、 2 5、 2 6、 2 7、 3 0、 3 1 、 3 2、 3 3、 3 4、 3 5、 3 6、 3 7、 4 0、
4 1 、 4 2、 4 3、 4 4、 4 5、 4 6、 4 7、 5 0、 5 1 、 5 2、 5 3、 5 4、 5 5、 5 6、 5 7、 6 0、 6 1 、 6 2、
6 3、 6 4、 6 5、 6 6、 6 7、 7 0、 7 1 、 7 2、 7 3、 7 4、 7 5、 7 6、 7 7、 1 0 0 . . .
最后一个数字读作“幺零零”,是卡通人物拥有的手指数自乘的结果(即平方)。
在写十进制或八进制数时,为避免混淆,可以借助使用特定的标记以区别表示数字系统。下面用标记“ T E N”表示十进制数,标记“ E I G H T”表示八进制数。
注意,在上面一系列的八进制数中,有一些好整数,像 1 0 0∨EIGHT(ps:EIGHT其实就是下标格式,只不过复制过来后格式就没了,只能暂时这样表示了)、 2 0 0∨EIGHT、 4 0 0∨EIGHT。好整数通常是指结尾有一些零的数。在结尾处有两个零的十进制数意味着它是 1 0 0∨TEN即 1 0∨TEN乘以1 0∨T E N;在八进制数中,结尾处有两个零表示它是 1 0 0∨EIGHT即 1 0∨EIGHT乘以 1 0∨EIGHT(或 8∨TEN乘以 8∨TEN,等于 6 4∨TEN)。
你可能已经注意到了,好的八进制整数 1 0 0∨EIGHT、 2 0 0∨EIGHT和4 0 0∨EIGHT与十进制数6 4∨TEN、 128∨TEN、
2 5 6∨TEN相等,它们都是 2的整数次幂。例如, 4 0 0 ∨EIGHT等于 4∨EIGHT乘以 1 0∨EIGHT乘以 1 0∨EIGHT,所有这些
数都是 2的整数次幂。任何时候,将 2的整数次幂和另一个 2的整数次幂相乘,得到的仍是 2的整数次幂。
下表给出了一些 2的整数次幂的十进制及其对应的八进制的表示形式:
最右边一列的好整数给我们一个暗示:十进制以外的数字系统可能对使用二元码有所帮助。
八进制数字系统和十进制数字系统在结构上没有什么差别,只是在细节上有一些差异。例如,八进制数的每一个位置代表的值是该位数字乘以 8的整数次幂的结果:
这样,八进制数 3 7 2 5∨EIGHT可以拆分成这样:
还可以写成另外几种不同的形式。下面就是其中的一种,采用十进制形式的 8的整数次幂:
采用八进制形式的 8的整数次幂的情况:
还有另外的一种拆分形式:
如果算出其十进制的结果,会得到 2 0 0 5∨TEN。这就是将八进制数转换成十进制数的方法。
可以采用与做十进制加法和乘法相同的办法来做八进制数的加法和乘法。唯一真正的区别在于要采用不同的表格来对各个数字进行乘法或加法运算。下面是八进制数的加法表:
例如, 5∨EIGHT + 7∨EIGHT = 14∨EIGHT。可以采用与做十进制加法相同的方法将两个稍长一点儿的八进制数相加:
先从最右边的一列做起, 5加上3 等于 1 0,该位写下 0,向前进 1 ; 1 加 3 加 4等于 1 0 ,该位写下0,向前进 1 ; 1 加1 加6等于1 0。
同样,在八进制中, 2乘以 2仍然等于 4。但是 3 乘以 3 却不等于 9,那是多少呢? 3乘以 3 等于,此数与
所代表的数量相等。下图是完整的八进制数的乘法表:
这里, 4× 6等于,也即表明
和4× 6的十进制结果
是等值的。
八进制数字系统与十进制数字系统一样,都是有效的,但八进制数字系统在理解上更深了一层。既然我们已为卡通人物开发出了一套数字系统,就再给龙虾开发一套适合它们用的数字系统吧。龙虾根本没有手指,但它两只前爪的末端都有螯。适合于龙虾的数字系统是四进制数字系统或称为基于 4的数字系统:
四进制数可以这样来数:
0、 1 、 2、 3 、 1 0、 11 、 1 2、 1 3 、 2 0、 2 1 、 2 2、 2 3 、 3 0、 3 1 、 3 2、 3 3 、 1 0 0、 1 0 1 、 1 0 2、
1 0 3、 11 0,等等。
这里不打算在四进制数上花太多的时间,因为还有更重要的事情要做。但我们还是要看一下四进制中的每一位是怎样和 4的某个整数次幂相对应的:
四进制数 3 1 2 3 2可以写成:
也可以写成:
还可以写成:
如果以十进制数的形式计算其结果,就会发现 。
现在,我们要做一个跳跃并且是最远的一跳。假定我们是海豚,并且必须用两鳍来数数。则这个数字系统就是基于 2的数字系统或二进制的。这样似乎只需要两个数字,即 0和1 。
现在, 0和 1 已是你要处理的全部问题,需要练习一下才能习惯使用二进制数。二进制数最大的问题是数字用完得很快。例如,下图是海豚怎样用它的鳍数数的例子:
是的,在二进制中, 1后面的数字是1 0。这是令人惊讶的,但也并不奇怪。无论使用哪种数字系统,当单个位的数字用完时,第一个两位数字都是1 0。在二进制系统中,可以这样来数数:
0、 1 、 1 0、 11 、 1 0 0、 1 0 1 、 11 0、 111、 1 0 0 0、 1 0 0 1 、 1 0 1 0、
1 0 11 、 11 0 0、 11 0 1 、 111 0、 1111、 1 0 0 0 0、 1 0 0 0 1 、……
这些数看起来好像很大,实际上并不是这样。更准确地说二进制数长度增长的速度要快过二进制数增大的速度:
在多位二进制数中,数字的位置和 2的整数次幂的对应关系为:
因此,任何时候由一个 1 后跟几个零构成的二进制数一定是 2的整数次幂。 2的幂与二进制数中零的个数相等。下面是扩充的 2的各次幂的表,可用来说明这条规则:
假定有一个二进制数 1 0 11 0 1 0 11 0 1 0,它可以写成:
也可以这样写:
如果将各个部分以十进制数的形式相加,得到
将二进制数转换成十进制数非常简单,你可能更喜欢借助已准备好的模板进行转换:
这个模板允许你转换最大长度为 8的二进制数,但它扩充起来非常容易。使用时,将 8个二进制数字放到上部的 8个小盒子中,一个盒子放一个数字。做 8个乘法运算,将结果分别放到底部的 8个小盒子中。将 8个盒子中的数字相加就得到最终结果。下面是将 1 0 0 1 0 11 0转化成十进制数的例子:
将十进制数转换成二进制数就没那么直接了。但这里也有一个帮助你将 0~ 2 2 5范围内的十进制数转换成二进制数的模板:
实际转化过程要表面上看的麻烦得多,所以一定要仔细按照下面的指导来做。将整个十进制数(应小于等于 2 2 5)放在左上角的方格中。用除数( 1 2 8)去除那个数(被除数),如下图所示。将商写在正下方的盒子中(即左下角的盒子中) ,余数写在右边的盒子中(即上面一行左数第二个盒子中) 。用第一个余数再除以下一个算子 6 4。依照模板的顺序用同样的方法继
续做下去。
记住,每次求得的商只能是 0或者1 。如果被除数小于除数,商为 0,余数和被除数相等;如果被除数大于除数,商为 1 ,余数为被除数与除数之差。下面是将 1 5 0转换成二进制数的过程:
如果要做两个二进制数的加法或乘法,也许直接采用二进制来做比转化成十进制再做还要简单。这将是你真正喜欢二进制数的地方。如果只需记住下面的二进制加法表就可以做加法运算,也就不难想象掌握加法运算该有多快:
用二进制加法表将两个二进制数相加:
从最右边的一列开始做起:1加上0等于1;右数第 2列: 0加上1 等于1 ;第 3列: 1 加上1等于0,进位为 1 ;第4列: 1 (进位值)加上 0再加上0等于1 ;第5列: 0加上1 等于1 ;第6列: 1加1 等于0,进位为 1 ;第7列: 1 (进位值)加上 1 再加上0等于1 0。
乘法表比加法表更简单,因为该表可以由两个基本的乘法规则推导出来:零乘以任何数都等于 0, 1 与任何数相乘仍是那个数本身:
人们在使用二进制数的时候通常将它们写成带有前导零的形式(即第一个 1 的左边有零)。例如, 0 0 1 1 而不写成 11 。这些零不会改变数字的值,只是起到一些装饰作用。例如,下面是二进制的前 1 6个数以及和它们等值的十进制数:
让我们再仔细看看这些二进制数字。考虑一下这 4个垂直列中每一列的 0和 1 ,注意它们在一列中自上而下是以怎样的规律变化的:
• 最右边一列一直在 0和1 之间相互替换。
• 右数第 2列在两个 0和两个1 之间相互替换。
• 右数第 3列在四个 0和四个1 之间相互替换。
• 右数第 4列在八个 0和八个1 之间相互替换。
这是很有规律的,难道不是吗?事实上,只要再重复这 1 6个数字并且在每个数字的前面放一个1 就可以很容易地写出后面的 1 6个数字:
下面是看待这些数字的另一种方式:在数二进制数的时候,最右边的数字(也称最低位数字)是在 0和1 之间变化的。当它每次从 1 变到 0时,右数第二位数字(也称次低位数字)也要发生变化,或者从 0变到 1 ,或者从 1 变到 0。每次只要有一个二进制数位的值由 1 变到 0,紧挨着的高位数字也会发生变化,要么从 0变到1 ,要么从 1 变到0。
我们在写十进制中比较大的数字时,通常每三个数字之间留一点儿空隙,这样,我们一看就知道这个数的大概数值。例如,当你看到数字 1 2 0 0 0 0 0 0 0时,你可能不得不去数其中 0的个数,但如果看到的是 120 000 000,则马上就能知道是一亿两千万。
二 进 制 数 的 位 长 度 增 加 得 特 别 快 。 例 如 , 一 亿 两 千 万 的 二 进 制 表 示 为 :1 0 11 0 1 11 0 0 0 11 0 11 0 0 0 0 0 0 0 0。为了让它更易读,通常是每四个数字之间用连字符或空格来分开。例如; 1 0 11 - 0 111 - 0 0 0 1 - 1 0 11 - 0 0 0 0 - 0 0 0 0或1 0 11 0 111 0 0 0 11 0 11 0 0 0 0 0 0 0 0。本书的后面会讲到更简单的二进制数的表示方法。
通过将数字系统减少至只有 0和 1 两个数字的二进制数字系统,我们已经在能够接受的范围内做了深入的讨论。不可能找到比二进制数字系统更简单的数字系统了。二进制数字系统架起了算术与电之间的桥梁。前面各章中,我们所看到的开关、电线、灯泡、继电器等物体都可以表示二进制数 0和1 :
电线可以表示二进制数字。有电流流过电线代表二进制数字 1 ;如果没有,则代表二进制数字0。
开关可以表示二进制数字。如果开关闭合,代表二进制数字 1 ;如果开关断开,代表二进制数字0。
灯泡可以表示二进制数字。如果灯泡亮着,代表二进制数字 1 ;如果没亮,代表二进制数字0。
电报继电器可以表示二进制数字。继电器闭合,代表二进制数字 1 ;继电器断开,代表二进制数字 0。
二进制数与计算机密切相关!
大约在 1 9 4 8年,美国数学家 John Wilder Tukey (生于 1 9 1 5年)提前认识到二进制数将在未来几年中随着计算机的流行而发挥更大的作用。他决定创造一个新的、更短的词来代替使用起来很不灵活的五音节词—binary digit。他曾经考虑用 b i g i t或b i n i t,但最后还是选用了短小、简单、精巧且非常可爱的单词 b i t (比特)来代替 binary digit这个词。