最近从零开始教儿子学编程,在讲解计算机是如何表示文本和数字的时候,儿子突然冒出了一个问题:

为什么要用不同的方式来表示?数字不也是文本吗?

这样一个看似天真的问题,差点把我给整不会了。

自从大学开始学习 C 语言以来,我们便习以为常的接受「字符串」和「数值」类型,从来没有深入去思考过「为什么」。听到这个问题的时候,我愣了一下,突然意识到我的编程入门是那么的晦涩难懂,为了让儿子更系统性的理解计算机的底层原理,我不得不重构一下整个知识框架。

最小单位

文本的最小单位

为了回答儿子的问题,我没有立刻进入二进制,而是先换了一个角度。

我问他:

如果把数字和文本拆到最小,它们各自剩下什么?

文本的最小单位是 ——「符号」

对于文本来说,最小单位是字符。

  • ‘A’ 是一个符号
  • ‘中’ 是一个符号
  • ‘?’ 也是一个符号

字符本身并不携带“数量”的概念,它只是被人类赋予了某种意义。
计算机所做的,只是把这些符号映射成编号,然后原封不动地存起来。

字符之间不存在天然的数学关系。

数字的最小单位

而数字不一样。

数字的最小单位不是「符号」,而是 ——「值」。

当我们写下 123 时,并不是在写三个符号,而是在表达一个数量。这个数量,可以被拆解、被计算、被组合。

然而,在一连串的符号中,每一个符号的位置对于如何表示整个文本并没有直接的关系,但在数字中,每一个数的位置本身就携带着信息。

在十进制中:

  • 3 出现在个位,表示 3
  • 3 出现在十位,表示 30
  • 3 出现在百位,表示 300

同一个符号,因为位置不同,含义完全不同。

这就是 Place Value (位值)的概念,位值的出现,是一个非常深刻的抽象:它意味着 —— 信息不仅存在于符号中,也存在于位置中。

而 Place Value (位值)这个概念,正是 Positional Numeral System 的重要组成部分。

Positional Numeral System

从小学到大学,从来没有哪本教科书上提到过这个概念,直到我在给儿子准备教材的时候,我才意识到这个概念是如此的重要,以至于不得不把它纳入编程入门的第一个章节。

当“符号 + 位置”共同决定一个数的大小时,我们就进入了 Positional Numeral System(位值制)。

我们日常使用的是十进制位值制:

每一位的“值”,取决于:

  • 它本身的「符号」
  • 它所在的「位置」

十进制如此,二进制也如此:

区别只是:

  • 使用多少个「符号」
  • 每一位的「权重」是多少

而计算机选择二进制,并不是因为它“高级”,只是数学上的自然选择:

  • 两种状态 → 完美契合电子电路的物理状态(通/断、高/低电平),易于实现高可靠性和稳定性
  • 位值制 → 运算规则简单,最可扩展

符号的数字化

字符本身没有“大小”或“数量”的含义。

字母 A 并不是“比 B 小 1”,汉字「中」也不存在自然的数学顺序。

于是,我们做了一件很工程化的事情 —— 给字符编号。

  • ASCII:A = 65
  • Unicode:中 = U+4E2D

注意这里的关键点:

文本在计算机中,是“被映射成数字”的

也就是说:

  • 数字 → 天生就是数
  • 文本 → 被人为编码成数

这两者在底层虽然都用 0 和 1 表示,但来源完全不同。

文本 vs 数字

如果你把 “123” 当成文本:

  • 你能拼接它:”123” + “4” = “1234”
  • 但不能直接计算

如果你把 123 当成数字:

  • 你能计算:123 + 4 = 127
  • 但它不再“有字符意义”

为什么不能一视同仁?

儿子当时又追问了一句:

那为什么不干脆都当成文本呢?

这是一个很自然的想法,但答案也很直接:

因为那样会让计算变得极其低效,甚至不可能。

Positional Numeral System 的意义,不在于“能表示”,而在于“能计算”。

  • 加法、乘法、比较大小
  • 溢出、精度、符号位

这些能力,都是 Positional Numeral System 天然支持的。

而文本,只能靠一层又一层的解释去“模拟”这些行为。

结语

回顾我们之前学习编程的顺序,几乎是混乱的,完全没有系统性。

我们往往从二进制、变量、类型、语法开始,却默认学生“自然就懂”数字是什么、文本是什么、计算是如何发生的,很多问题就只能死记硬背。当真正理解了 Positional Numeral System 这个所有数值抽象的源头之后,一切突然就变得豁然开朗。