编码的奥秘:字节与十六进制

转自:《编码的奥秘》     第十五章

            上一章中的两个改进的加法机清晰地解释了数据路径的概念。在整个电路中, 8位值从一个部件传到另一个部件。它们是加法器、锁存器、选择器的输入,经过运算或操作又从这些部件输出。这些数由开关定义,最后由灯泡来表示结果。可以认为电路中的数据路径的宽度是8位。可是,为什么一定是 8位,而不是 6位、 7位、 9位或1 0位呢?

             最简单的回答就是这些加法机是在第 1 2章中最原始的加法机上改进而来的,而最原始的那个加法机就是 8位。不过,这个解释似乎很缺乏说服力。实际上,用 8位的原因是它表示一个字节。

            字节这个词大概是在 1 9 5 6年前后由 I B M公司最早提出来的。这个词起源于 b i t e,但用 y代替了 i,以便不会被人误认为它是 b i t。曾经有一段时期,字节仅仅简单地表示特定数据路径上数据的位数。但是到了 2 0世纪 6 0年代中期,随着 I B M的3 6 0系统的发展(一种大型复杂的商用计算机) ,字节这个词专门用来表示 8位二进制数。

            作为一个 8位数,一个字节可以从 0 0 0 0 0 0 0 0取值到 11111111。这些数可以代表 0~2 5 5的正数,也可以表示 - 1 2 8~1 2 7范围之内的正、负数。总之,一个特定的字节可以代表 2^8即 2 5 6种不同事物中的一个。

           8位数事实上是很适用的,字节在很多方面都比一位数优越。 I B M采用字节的一个原因就是它们易于以 B C D(将在第 2 3章中描述)这种格式保存。巧的是,在以后的各章中你会看到字节用于保存文本也是很合适的,因为世界上大部分书面语言都可以用少于 2 5 6个字符的字符集来表示(除了汉语、日语、韩语等所用的表意文字以外)。用字节表示黑白图像中的灰度也是很合适的,因为人眼大约能区分 2 5 6种不同程度的灰度。当一个字节不足以表示信息时(如刚才说的表意语言:汉语、日语、韩语等),用两个字节,即 2 1 6或65 536也可以很好地表示。

           半个字节,即 4位二进制数,有时被称为半位元组 ,它比起字节而言,用的并不频繁。

           由于字节在计算机内部经常出现,所以尽可能简单明了地表示它会带来很大方便。例如,一个8位二进制数 1 0 11 0 11 0的确很直观但是不简明。

          当然也可以用十进制数来表示字节,但这要求从二进制换算成十进制,这样做不仅不简单,反而是件很令人讨厌的事。第 8章曾描述了一种很直观的方法。每一位二进制数字写到对应的方盒子中,并在其下方标上 2的乘方数。把每一列相乘后再相加即可得到对应的十进制数。下面是 1 0 11 0 11 0的转换:

扫描二维码关注公众号,回复: 4420571 查看本文章

          把十进制数转换为二进制数就更麻烦了。你可以用十进制数去除以以递减顺序排列的 2的幂,每除一次,商是一个二进制位,而余数则继续去除以下一个最大的 2的幂。下面是十进制数1 8 2转换成对应二进制数的过程:


           第8章有关于这个方法的更多描述。总之,在十进制数和二进制数之间进行转换通常不是件十分简单的事。

            从第8章中我们还学习了八进制数字系统,八进制数字系统只使用数字 0、 1 、 2、 3、 4、 5、6、 7。在八进制数和二进制数之间进行转换却是小菜一碟,你只要记住每个八进制数字对应 3位二进制数字即可,如下表所示:

           
            如果已有一个二进制数字(如 1 0 11 0 11 0),则从最右边的数字开始,每 3 位二进制数字组成一组,即可转换为对应的八进制数:

           可见,字节 1 0 11 0 11 0可以表示为八进制的 2 6 6。 这显然已简单了很多,八进制确实是表示字节的一个好方法,但其中仍然有一个问题。

           字节的二进制表示范围是从 0 0 0 0 0 0 0 0~11111111,对应的八进制表示范围是从 0 0 0~ 3 7 7。上例清楚地表示出 3 位二进制数对应于最右边和中间的八进制数,而 2位二进制数对应于最左边的八进制数,这就表明一个 1 6位二进制数的八进制表示和把它分成两个字节后的八进制表示有所不同:


              为了使多字节值能和单字节值的表示一致,需要的系统应该能使每个字节平分,这意味着应该把每个字节分成 4组,每组 2位(以4为基数);或2组,每组 4位(以1 6为基数)。

               让我们看看以 1 6为基数的情况,这是我们还未接触过的新的记数系统。它被称为“十六进制( h e x a d e c i m a l)”,这个词本身就让人迷惑,因为大部分以 h e x a -为前缀的词都是指与 6有关的事物,而这里 h e x a d e c i m a l却是指 1 6。虽然微软公司在技术出版物的格式方面明确地声明不要将十六进制缩写为 hex ,但绝大多数人还是使用这种缩写。

              在十进制中,我们这样计数:

               在八进制中,不需要 8和9:

              同样,以 4为基数的系统不需要 4、 5、 6或7:


              而二进制只需要 0和1 :

              但是十六进制有些不同,它需要的符号比十进制还要多,如下所示:

               上图中 1 0出现的地方是表示十进制中的数 1 6。此外,还需要 6个符号来表示十六进制数,但这些符号是什么呢?它们来自哪里呢?最形象的方法是引入 6个新符号,例如:


                 它们不同于大部分数字用的符号,这些符号的优点是便于记忆,而且从某种意义上代表了它们应该表示的数字。你看,重 1 0加仑的牛仔帽、一个橄榄球(一个橄榄球队有 11 人)、一打椰子、一只黑猫(和不吉利的 1 3相联系) 、一轮满月(一般出现在新月后的第 1 4天晚上)以及让人们联想到 Julius Caesar 在三月的第 1 5天被暗杀时所用的匕首。

                  每个字节都可以用两个十六进制数表示,换句话说,一个十六进制数代表 4位二进制数,即半个字节。下表描述了在二进制数、十六进制树和十进制数之间的转换:

          下图表示如何用十六进制表示字节 1 0 11 0 11 0:


           即使要表示多字节数也很容易:

           一个字节总是由一对十六进制数来表示。

          不过,我们绝不会真的用橄榄球或匕首来表示十六进制数,事实上,我们用 6个拉丁字母来表示那 6个十六进制数,如下所示:


           下表表示出在二进制数、十六进制数和十进制数之间的转换:

           字节1 0 11 0 11 0可以由十六进制数 B 6来表示,而不用再画上一个橄榄球。同前面的章一样,用下标来表示记数系统的基数,如:表示二进制、表示四进制、 表示八进制、 表示十进制、则表示十六进制。不过,这真是挺麻烦的。还好,有更简单、更通用的方法来表示十六进制: 还可以进一步简化为

           在十六进制数中,每一位的位置都对应于 1 6的幂:

         十六进制数 9 A 4 8 C h是:

          用 1 6的乘方表示为:


         用对应的十进制数代入为:

        注意,在写一个数时,不用下标来表示数的基数也不会引起混淆。 9就是 9,不管它是十进制数还是十六进制数;而 A则显然是个十六进制数,相当于十进制中的 1 0。

        把所有数字转换成十进制数需要下列运算:


        答案是 631 948。以上是一个十六进制数如何转换成十进制数的过程。

         下面是把任何一个 4位十六进制数转换成十进制数的模板:



         例如,这儿有一个7 9 A C h的转换过程。记住,十六进制中的A和C对应于十进制中的1 0和1 2:

        把十进制数转换为十六进制数需要做除法。如果数字比 2 5 5小,则可以用 1 个字节来表示,对应于两个十六进制数。为了求出这两个数,用原数去除以 1 6得到商和余数。举例说明, 1 8 2除以 1 6得11 ,余6,所以十六进制表示为 B 6 h。

         如果想要转换的十进制数比 65 536小,则十六进制表示会有 4位或更少。下面是把这样一个十进制数转换为十六进制数的一个模板:



          先把整个十进制数放到左上角的盒子里,作为第一个被除数,用它除以 4 0 9 6(第一个除数) ,商放到被除数下面的盒子里,余数放到被除数右边的盒子里。余数成为新的被除数,用它除以 2 5 6。以下是 31 148如何转换成十六进制数的过程:


          当然,十进制数的 1 0和1 2用十六进制表示就是 A和C,故结果是 7 9 A C h

          这个方法的问题是如果你想用一个计算器来做除法运算,它不会显示出余数是多少。如果你用 31 148 除以 4 0 9 6,计算器给出的结果只能是 7 . 6 0 4 4 9 2 1 8 7 5。为了计算余数你得用 4 0 9 6× 7(得到 28 672 ),再从 31 148 中减去它;或者用 4 0 9 6乘以 0 . 6 0 4 4 9 2 1 8 7 5,即商的小数部分。 (不过,有些计算器具有十进制数和十六进制数之间的转换功能。 )

            把小于 65 535 的十进制数转换为十六进制数的另一个方法是先把原数除以 2 5 6而分为两个字节,对于每个字节,再除以 1 6。下面是模板:

           
         从最上面开始,每做完一次除法,商就进入除数左下方的盒子里,而余数进入右边的盒里里。例如, 51 966的转换过程是:

         
          得到的十六进制数字是1 2、 1 0、 1 5和1 4,即C A F E,它看起来倒更像一个单词而非一个数字!

          下面是和十六进制相关的加法表:


             可以用这张表和通常的进位规则来对十六进制数做加法:

             
            曾在第 1 3 章中讲过可以用 2的补数来表示负数。如果在二进制中处理 8位带符号数,则所有的负数都是以 1 开头的。在十六进制中,两位带符号数若是以 8、 9、 A、 B、 C、 D、 E或F开头则是负数。例如, 9 9 h可能表示十进制的 1 5 3(如果处理的是 1 个字节的无符号数)或十进制的- 1 0 3(如果处理的是有符号数)。

             字节9 9 h也有可能就是十进制的 9 9,关于这一点会在第 2 3章中解释,但是下一步必须先讲讲存储器。

(ps: 这章比上一章和蔼多了,没有那么多晦涩的电路图~)

关注微信公众号: 程序猿的那些事儿哈

猜你喜欢

转载自blog.csdn.net/qq_32523587/article/details/84205261