计算机可以处理文字、图片、视频、程序、网站、游戏,甚至人工智能。
这一切看起来极其复杂。
但在所有这些复杂功能的最底层,却存在一个出奇简单的基础:
二进制(Binary)。
二进制只使用两个数字:
|
1 2 3 |
0 1 |
就是这两个简单的数字,构成了现代数字计算机的基础。
CPU 寄存器保存的是比特,内存保存的是比特,机器指令使用比特编码,文件和网络数据最终也都会变成一串串 0 和 1。
因此,在理解 CPU、内存、数字逻辑以及计算机体系结构之前,我们首先需要真正理解:
二进制到底是什么?
本文主要介绍:
- 什么是二进制
- 为什么计算机使用二进制
- 什么是 Bit 和 Byte
- 二进制的位权
- 二进制如何转换成十进制
- 十进制如何转换成二进制
- n 个 Bit 可以表示多少种状态
- 无符号二进制整数
- 二进制加法
下一篇我们会进一步讨论:
同样的一串 0 和 1,为什么既可以表示数字,也可以表示字符、CPU 指令、内存地址、图片和其他数据。
1. 什么是二进制?
我们平时使用的是十进制(Decimal)。
十进制又称为 Base 10,因为它一共有 10 个数字:
|
1 2 |
0 1 2 3 4 5 6 7 8 9 |
二进制则不同。
二进制只有两个数字:
|
1 2 |
0 1 |
所以二进制又称为:
Base 2
例如下面就是一个二进制数:
|
1 2 |
1101 |
第一次看到它,很多人可能觉得很奇怪。
实际上,二进制和十进制使用的是完全相同的“位置计数”思想。
每个数字的实际数值,都由它所在的位置决定。
区别只是:
- 十进制使用 10 的幂
- 二进制使用 2 的幂
【英文配图:Decimal vs Binary / Base 10 vs Base 2】
2. 为什么计算机使用二进制?
一个很自然的问题是:
为什么计算机内部使用 0 和 1?
为什么不能直接使用我们熟悉的十进制?
原因主要来自电子硬件。
数字电路非常适合可靠地区分两种逻辑状态。
例如可以简单理解为:
|
1 2 3 |
Low Voltage → 0 High Voltage → 1 |
晶体管组成的电路也可以近似理解为电子开关:
|
1 2 3 |
OFF → 0 ON → 1 |
真实的数字电子电路当然比简单的“开”和“关”复杂得多,但这种两状态模型非常重要。
对于电子电路来说,可靠地区分两个电压范围,要比精确地区分 10 个不同电压等级容易得多。
因此:
二进制天然适合数字电子系统。
工程师可以从简单的 0 和 1 开始,一步步构造出:
所以二进制并不仅仅是一种数学上的选择。
它与数字硬件的物理实现紧密相关。
【英文配图:LOW/HIGH → 0/1 → Logic Gates → CPU】
3. 什么是 Bit?
数字信息最基本的单位叫做:
Bit,比特。
Bit 这个词来自:
Binary Digit
也就是“二进制数字”。
一个 Bit 只能拥有两个可能的值:
|
1 2 |
0 |
或者:
|
1 2 |
1 |
因此,一个 Bit 可以表示两种状态。
例如:
|
1 2 3 |
0 → OFF 1 → ON |
也可以表示:
|
1 2 3 |
0 → False 1 → True |
甚至:
|
1 2 3 |
0 → No 1 → Yes |
至于 0 和 1 究竟代表什么,要由具体系统来决定。
这里最重要的概念是:
一个 Bit 只有两种可能状态。
4. Bit 越多,可以表示的状态越多
一个 Bit 有两种可能:
|
1 2 3 |
0 1 |
两个 Bit 就有四种组合:
|
1 2 3 4 5 |
00 01 10 11 |
三个 Bit 有八种:
|
1 2 3 4 5 6 7 8 9 |
000 001 010 011 100 101 110 111 |
每增加一个 Bit,可能的组合数量都会翻倍。
因此有一个非常重要的公式:
|
1 2 |
n bits = 2^n possible patterns |
也就是:
n 个 Bit 可以产生 2ⁿ 种不同的二进制组合。
例如:
| Bit 数量 | 可表示的组合数量 |
|---|---|
| 1 | 2 |
| 2 | 4 |
| 3 | 8 |
| 4 | 16 |
| 5 | 32 |
| 8 | 256 |
| 16 | 65,536 |
| 32 | 4,294,967,296 |
例如 5 个 Bit:
|
1 2 |
2^5 = 32 |
所以可以产生 32 种不同的组合。
这也是为什么在很多 CPU 体系结构中,如果需要从 32 个对象中选择一个,只需要一个 5-bit 编号。
【英文配图:1 Bit → 2 / 2 Bits → 4 / 3 Bits → 8 / n Bits → 2ⁿ】
5. 先理解十进制的位权
在学习二进制位权之前,我们先看一个普通的十进制数:
|
1 2 |
527 |
这里三个数字的价值并不相同。
7 在个位。
2 在十位。
5 在百位。
所以:
|
1 2 |
527 |
实际上表示:
|
1 2 3 4 5 6 |
5 × 100 + 2 × 10 + 7 × 1 |
也就是:
|
1 2 3 4 5 6 |
5 × 10² + 2 × 10¹ + 7 × 10⁰ |
它的位权分别为:
|
1 2 |
100 10 1 |
每向左移动一位,位权就乘以 10。
这就是为什么十进制叫做:
Base 10。
6. 二进制的位权
二进制使用完全相同的原理。
区别只是:
每向左移动一位,不是乘以 10,而是乘以 2。
二进制的位权是:
|
1 2 |
... 128 64 32 16 8 4 2 1 |
对应:
|
1 2 |
2⁷ 2⁶ 2⁵ 2⁴ 2³ 2² 2¹ 2⁰ |
从右向左:
|
1 2 3 4 5 6 7 8 9 10 11 |
1 2 4 8 16 32 64 128 256 ... |
每向左一位,数值翻倍。
这是理解二进制最重要的基础之一。
【英文配图:Binary Place Values — 128 64 32 16 8 4 2 1】
7. 如何读取一个二进制数?
来看:
|
1 2 |
1101 |
它一共有 4 个 Bit。
对应的位权为:
|
1 2 |
8 4 2 1 |
把它们放在一起:
|
1 2 3 |
Binary: 1 1 0 1 Place Value: 8 4 2 1 |
二进制中的 1 表示:
这个位权需要计算进去。
0 表示:
这个位权不计算。
因此:
|
1 2 |
1101 |
实际上就是:
|
1 2 |
8 + 4 + 0 + 1 |
结果为:
|
1 2 |
13 |
所以:
|
1 2 |
1101₂ = 13₁₀ |
下标 2 表示 Base 2,也就是二进制。
下标 10 表示 Base 10,也就是十进制。
8. 再看一个二进制转十进制的例子
例如:
|
1 2 |
10110 |
这是一个 5-bit 二进制数。
对应位权:
|
1 2 |
16 8 4 2 1 |
排列起来:
|
1 2 3 |
Binary: 1 0 1 1 0 Place Value:16 8 4 2 1 |
有 1 的位置分别是:
|
1 2 3 4 |
16 4 2 |
所以:
|
1 2 |
16 + 4 + 2 = 22 |
因此:
|
1 2 |
10110₂ = 22₁₀ |
9. 一些应该熟悉的 2 的幂
学习计算机体系结构时,不需要死记非常长的二进制数。
但是最好能够快速认出一些常见的 2 的幂:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
2⁰ = 1 2¹ = 2 2² = 4 2³ = 8 2⁴ = 16 2⁵ = 32 2⁶ = 64 2⁷ = 128 2⁸ = 256 2⁹ = 512 2¹⁰ = 1024 |
在计算机领域,我们会不断看到:
|
1 2 3 4 5 6 7 8 9 |
8 16 32 64 128 256 512 1024 |
这些数字频繁出现并不是巧合。
这是因为现代计算机建立在二进制基础之上。
10. 十进制如何转换成二进制?
假设我们要把十进制:
|
1 2 |
13 |
转换成二进制。
先写出位权:
|
1 2 |
8 4 2 1 |
13 中有没有 8?
有。
所以第一位:
|
1 2 |
1 |
剩下:
|
1 2 |
13 - 8 = 5 |
5 中有没有 4?
有。
第二位也是:
|
1 2 |
1 |
剩下:
|
1 2 |
5 - 4 = 1 |
1 中有没有 2?
没有。
所以:
|
1 2 |
0 |
最后 1 中有 1:
|
1 2 |
1 |
最终得到:
|
1 2 |
1101 |
也就是:
|
1 2 |
13₁₀ = 1101₂ |
【英文配图:Decimal 13 → 8 + 4 + 1 → 1101】
11. 除 2 取余法
还有一种非常常见的方法:
不断除以 2,并记录余数。
仍然以 13 为例:
|
1 2 3 4 5 |
13 ÷ 2 = 6 remainder 1 6 ÷ 2 = 3 remainder 0 3 ÷ 2 = 1 remainder 1 1 ÷ 2 = 0 remainder 1 |
然后从下往上读取余数:
|
1 2 |
1101 |
因此:
|
1 2 |
13₁₀ = 1101₂ |
两种方法得到完全相同的结果。
不过,如果要进一步学习 CPU 和计算机体系结构,最好还是逐渐熟悉 2 的幂和二进制位权。
12. 什么是 Byte?
一个 Bit 能表示的信息非常有限。
因此计算机通常会把多个 Bit 组合起来使用。
8 个 Bit 组成一个 Byte,也就是一个字节。
|
1 2 |
1 Byte = 8 Bits |
例如:
|
1 2 |
01000001 |
一共有 8 个 Bit,因此就是一个 Byte。
8 个 Bit 可以产生:
|
1 2 |
2⁸ = 256 |
种不同的组合。
最小的二进制组合是:
|
1 2 |
00000000 |
最大的组合是:
|
1 2 |
11111111 |
如果把它们解释为无符号整数(Unsigned Integer),范围就是:
|
1 2 |
0 ~ 255 |
【英文配图:8 Bits = 1 Byte = 256 Patterns】
13. 为什么 8 Bit 有 256 个值,最大却只有 255?
这是初学二进制时非常容易混淆的问题。
8 个 Bit 一共有:
|
1 2 |
2⁸ = 256 |
种组合。
既然有 256 种组合,为什么最大值不是 256,而是 255?
原因非常简单:
0 本身也占一个数值。
范围实际上是:
|
1 2 3 4 5 6 7 |
0 1 2 3 ... 255 |
从 0 到 255,总共正好有 256 个整数。
因此:
|
1 2 3 |
Number of Values = 256 Maximum Value = 255 |
一般来说,n 个 Bit 能表示的最大无符号整数为:
|
1 2 |
2ⁿ - 1 |
14. 无符号二进制整数
Unsigned Integer,无符号整数,只表示 0 和正整数。
例如使用 4 个 Bit:
|
1 2 3 4 5 6 7 |
0000 = 0 0001 = 1 0010 = 2 0011 = 3 ... 1111 = 15 |
4 个 Bit 有:
|
1 2 |
2⁴ = 16 |
种不同状态。
因此范围为:
|
1 2 |
0 ~ 15 |
因为:
|
1 2 |
2⁴ - 1 = 15 |
同样:
|
1 2 3 |
8-bit unsigned: 0 ~ 255 |
|
1 2 3 |
16-bit unsigned: 0 ~ 65,535 |
|
1 2 3 |
32-bit unsigned: 0 ~ 4,294,967,295 |
所以一般公式为:
|
1 2 3 4 |
Unsigned n-bit range: 0 ~ 2ⁿ - 1 |
15. 常见的数据宽度
现代计算机经常使用一些固定的数据宽度:
|
1 2 3 4 5 |
8 bits = 1 byte 16 bits = 2 bytes 32 bits = 4 bytes 64 bits = 8 bytes |
一个 32-bit 数值就是由 32 个二进制数字组成。
例如:
|
1 2 |
10110100 00101101 11100010 00010111 |
这里的空格只是为了方便人阅读。
对于计算机来说,这完全可以被看成连续的 32 个 Bit。
随着 Bit 数增加,可以表示的状态数量会以极快的速度增长。
32 个 Bit:
|
1 2 |
2³² |
种组合。
64 个 Bit:
|
1 2 |
2⁶⁴ |
种组合。
这也是为什么 8-bit、16-bit、32-bit、64-bit 在计算机体系结构中如此重要。
【英文配图:8-bit → 16-bit → 32-bit → 64-bit】
16. 二进制加法
计算机不仅保存二进制数据,还必须对它们进行运算。
二进制加法和十进制加法的基本思想非常相似。
只需要记住四种基本情况:
|
1 2 3 4 5 |
0 + 0 = 0 0 + 1 = 1 1 + 0 = 1 1 + 1 = 10 |
其中最重要的是:
|
1 2 |
1 + 1 = 10 |
为什么?
在十进制中:
|
1 2 |
9 + 1 = 10 |
我们把 0 留在当前位,把 1 进到更高一位。
二进制也一样。
因为二进制只有 0 和 1,所以:
|
1 2 |
1 + 1 |
等于十进制的 2,而十进制 2 用二进制表示就是:
|
1 2 |
10 |
也就是:
当前位写 0,向下一位进 1。
17. 一个简单的二进制加法
例如:
|
1 2 3 4 |
0101 + 0011 ------ |
先看看它们的十进制值:
|
1 2 3 |
0101₂ = 5 0011₂ = 3 |
所以结果应该是:
|
1 2 |
8 |
进行二进制加法:
|
1 2 3 4 5 |
0101 + 0011 ------ 1000 |
而:
|
1 2 |
1000₂ = 8₁₀ |
因此:
|
1 2 |
0101₂ + 0011₂ = 1000₂ |
数学运算本身没有改变。
改变的只是数制。
18. 带进位的二进制加法
再来看:
|
1 2 3 4 |
0111 + 0001 ------ |
从最右边开始:
|
1 2 |
1 + 1 = 10 |
当前位写:
|
1 2 |
0 |
并向左进 1。
下一位又变成:
|
1 2 |
1 + Carry 1 = 10 |
再次写 0,继续进位。
最终:
|
1 2 3 4 5 |
0111 + 0001 ------ 1000 |
十进制就是:
|
1 2 |
7 + 1 = 8 |
这种 Carry,也就是进位传播,以后学习数字电路中的加法器时非常重要。
【英文配图:Binary Addition / Carry Propagation】
19. 为什么二进制加法如此重要?
二进制加法看起来只是一个简单的数学问题,但它直接连接到 CPU 硬件。
在处理器内部,有一种专门执行二进制加法的数字电路:
Adder,加法器。
一个最基本的加法器需要解决两个问题:
- 当前位的结果是多少?
- 是否需要向下一位产生 Carry?
通过组合不同的 Logic Gates,就可以完成这些工作。
然后再把许多个基本加法电路连接起来,就可以构造:
- 8-bit Adder
- 16-bit Adder
- 32-bit Adder
- 64-bit Adder
因此:
二进制加法是数字表示与 CPU 硬件之间的一座桥梁。
以后我们介绍 Half Adder、Full Adder、32-bit Adder 和 CPU ALU 时,还会继续回到这里。
【英文配图:Bits → Logic Gates → Adder → CPU】
20. LSB 和 MSB 是什么?
学习二进制时,还会经常看到两个术语:
LSB
最右边的 Bit 称为:
Least Significant Bit
简称:
LSB
也就是最低有效位。
MSB
最左边的 Bit 称为:
Most Significant Bit
简称:
MSB
也就是最高有效位。
例如:
|
1 2 3 4 |
10110010 ^ ^ MSB LSB |
对于一个 8-bit 无符号整数:
LSB 对应:
|
1 2 |
2⁰ = 1 |
MSB 对应:
|
1 2 |
2⁷ = 128 |
因此,改变左边高位 Bit,通常会比改变右边低位 Bit 对最终数值产生更大的影响。
21. 二进制真正重要的是“模式”
刚开始学习二进制时,我们很容易只把它理解为一种表示数字的方法。
但是更重要的概念其实是:
一组 Bit 构成了一种 Pattern,也就是比特模式。
例如:
|
1 2 |
01000001 |
这是一个 8-bit Pattern。
8 个 Bit 一共有 256 种可能的 Pattern。
但:
|
1 2 |
01000001 |
究竟代表什么?
它可以代表一个数字。
也可以代表一个字符。
还可以是 CPU 指令的一部分。
甚至可以是图片、音频或者其他数据的一部分。
真正决定含义的,并不是这一串 Bit 本身,而是:
计算机如何解释这串 Bit。
在本文中,我们主要把二进制模式解释为无符号整数。
下一篇,我们就会看到:
完全相同的 0 和 1,可以拥有完全不同的意义。
【英文配图:Same Bits → Number / Character / Instruction / Pixel】
22. 快速总结
二进制只使用:
|
1 2 |
0 和 1 |
每一个二进制数字叫做:
|
1 2 |
Bit |
8 个 Bit 组成:
|
1 2 |
1 Byte |
二进制位权是 2 的幂:
|
1 2 |
1, 2, 4, 8, 16, 32, 64, 128... |
n 个 Bit 可以产生:
|
1 2 |
2ⁿ |
种不同的组合。
n 个 Bit 所能表示的最大无符号整数为:
|
1 2 |
2ⁿ - 1 |
二进制加法和十进制加法同样存在进位,其中最基本的规则之一就是:
|
1 2 |
1 + 1 = 10 |
结语
二进制是现代计算机最重要的基础之一。
十进制有十个数字,而二进制只需要:
|
1 2 3 |
0 1 |
一个二进制数字叫做一个 Bit。
多个 Bit 组合在一起,就可以产生大量不同的二进制模式。
二进制中的每一个位置都是 2 的幂:
|
1 2 |
1, 2, 4, 8, 16, 32, 64... |
理解这些位权以后,二进制和十进制之间的转换就变得非常简单。
8 个 Bit 构成一个 Byte。
一个 n-bit 无符号二进制整数,可以表示:
|
1 2 |
0 ~ 2ⁿ - 1 |
而二进制加法中的:
|
1 2 |
1 + 1 = 10 |
看起来虽然简单,却已经开始把我们带向真正的数字硬件。
因为在 CPU 内部,二进制加法并不是由“软件想出来”的。
它是由晶体管、逻辑门和加法器电路真正完成的。
下一篇:
二进制在计算机内部:0 和 1 如何表示数据与指令
我们将进一步讨论同样的二进制模式如何表示:
- 负数
- 字符
- 内存数据
- CPU 寄存器
- 机器指令
- 内存地址
- 图片
- 其他数字数据
最重要的一个概念是:
计算机真正存储的并不是“数字”“文字”或者“指令”。
它存储的是 Bit Pattern——比特模式。
至于这些 0 和 1 究竟代表什么,则取决于我们如何解释它们。
