【译】TCP/IP 网络编程基础系列-数值编码

数值编码

存储在计算机中的每条信息都是以数字编码的形式存在的。

你现在正在阅读的句子,也是一个数字序列:每个字母都有一个数值与之对应,比如单词“hello”对应的 5 个数字是:104,101,108,108,111。

我们通常用的是名字叫做 UTF-8 的编码方案,该方案可以表示很多字符,包括符号,各个语言中的有序字符,和 emoji。虽然还存在其他的编码方式,但如今 UTF-8 是最常用的。

试试下面这些字母,是如何转变成数字的:

a b c d e f g
// 97 98 99 100 101 102 103

十进制和二进制

在我们的日常生活中,我们使用的是基于数字 10 的十进制数字:我们使用十、百、千等进行计数。这样,我们可以对事物计数:1 棵树、2 个苹果、10 个手指。但相同的数量是可以使用不同的符号和其他的数值系统来表示的。例如,我们使用罗马数字:I, II, III, IV, X。但是如果我们需要处理更大的数字时,这些数字并不是特别实用,另外,当使用计算机处理数据时,十进制数并不是很实用。

计算机使用二进制数值系统,从本质上讲,该数值系统和其他的数值系统没有什么太大区别。要了解这些数值系统,先让我们看看一个十进制数:123。我们可以将其解构为一些数字的和 (100+20+3),也可以将其解构为指数的和:

10^2 × 1 = 100 (1 百)
10^1 × 2 = 20 (2 十)
10^0 × 3 = 3 (3 个)

请注意,我们如何对数字 10 求幂:它是我们数值系统的底数或基数,可以看做它是用来计数的位数。例如:从零开始,以 10 为底的 0~9(10 进制),以 8 为底的 0~7(8 进制),以 2 为底的只有两个:0 和 1(2 进制)。指数可以看做数字的位置,比如 500,它由 3 个数字:5,0 和 0。5 是从右往左数第 3 位数字。我们可以将其看做是从 0 开始的列表或数组。从右边开始计数,5 位于索引为 2 的位置上。因此,我们将 10 的 2 次幂再乘以 5,即:10^2 * 5=500。

Something fun happens when we change the number base and follow the same principle of summing exponents. Let's see how it works in base 8: 777 oct is a sum of exponents:

当我们改变基数,并遵循相同的求和原理时,会发生一些有趣的变化。让我们看看在底数为 8 时的表现是怎样的:八进制的 777 的指数和如下:

8^2 × 7 = 448 (7 个 64)
8^1 × 7 = 56 (7 个 8)
8^0 × 7 = 7 (7 个 1)

如果我们将其转换为十进制,将数字进行求和 448 + 56 + 7,将会得到 511,这才是八进制数 777 的确切含义。

如果我们使用 2 作为基数,也是一样的。例如,二进制下的 1011。它可以分解为下面的指数公式的和:

2^3 × 1 = 8 (1 个 8)
2^2 × 0 = 0 (0 个 4)
2^1 × 1 = 2 (1 个 2)
2^0 × 1 = 1 (1 个 1)

如果我们将这些指数值求和,将会得到 11,这是二进制的 1011 所代表的的数值。

十六进制

但如果我们拥有超过 10 的数值系统呢?比如,十六进制,即以 16 作为基数。当我们数字用完了,我们可以用字母替代:如,十六进制中的 A 等于十进制中的 10,并且十六进制数字 B,代表 11,以此类推知道 F。

尝试如下数值:

1f(十六进制)
161 × 1 = 16 (1 个 16)
160 × 15 = 15 (15 个 1)

如果我们将其求和 16+15,会得到十进制的 31,即 16 进制的 1f。

我们在计算机中使用十六进制数值系统是因为它简洁的特性:我们表示一个字节(一个位于 0~255 之间的数)只需要 2 个十六进制数。这就可以让我们构建简洁的栅格或十六进制视图,即用十六进制数来表示数据序列。

让我们回到文章开始的文本编码示例,此时,我们使用十六进制对其进行编码:

abcdefg
// 61 62 63 64 65 66 67 hex

番外

作为数字机器的本质而言,计算机只能处理 0 和 1。通过文本编码和调整底数(基数),计算机可以处理人类每天使用的字母和数字。既然你已经知道数据是如何“在线”编码的,那么后续你将会学习到很多有关网络和底层编程的更多信息。

posted @ 2020-10-11 19:38  suhanyujie  阅读(402)  评论(0编辑  收藏  举报