现在位置: 首页 > 计算机组成原理 > 正文

为什么计算机只认识 0 和 1

本讲你将理解:计算机为什么选择了二进制而不是十进制,以及这一选择如何决定了现代计算机的整个架构。


从开关说起

想象你面前有一排电灯开关。

每个开关只有两种状态:

你不能让一个开关「半开」或「开 37%」——它是二态的,没有中间状态。

计算机内部最基本的元件——晶体管,本质上是和开关一样的东西。

它只有两种稳定状态:导通(通电)截止(断电)

电压的两种状态

在数字电路中,我们给这两种状态分别分配一个符号:

  • 高电压(比如 3.3V 或 5V)代表 1
  • 低电压(接近 0V)代表 0

电压与二进制的关系

下面这条色带模拟了晶体管从 0V 到 3.3V 的电压范围,直观展示逻辑 0、逻辑 1 和禁止区的关系。

0.0V
逻辑 0
. 0.5V 1.0V 1.5V
禁止区
1.8V
开始
2.1V 2.7V 3.3V
逻辑 1

逻辑 0 范围:0.0V ~ 1.5V(蓝色区域)  |  禁止区:1.5V ~ 1.8V(灰色区域,信号不会停留)  |  逻辑 1 范围:1.8V ~ 3.3V(橙色区域)

注意:电路不需要精确测量电压值,只需要判断「高还是低」。

这比判断「是几」要容易得多。


为什么不用十进制

人类使用十进制,因为我们有十根手指。

但为什么计算机不能用十进制呢?

理由一:工程实现极其困难

如果要让电路表示十进制的 10 个数字(0~9),电路需要精确区分 10 个不同的电压等级。

比如:0V = 0,0.33V = 1,0.66V = 2,...,3.3V = 9。

问题来了:信号在传输过程中会有损耗和干扰。

假设你发送了 0.66V 表示数字 2,但到达目的地时电压变成了 0.71V。

接收端就会困惑:这到底是 2(0.66V)还是 3(0.99V)?

理由二:二进制天然抗干扰

二进制只需要区分两种状态,容错空间极大。

如图:逻辑 0 的范围是 0~1.5V,逻辑 1 的范围是 1.8V~3.3V。

中间有 0.3V 的保护区。

即使信号有较大波动,只要不跨过保护区,数据就不会出错。

理由三:与数学完美契合

0 和 1 正好对应布尔代数中的「假」和「真」。

布尔代数(AND、OR、NOT 等逻辑运算)有一套完整的数学理论。

工程师可以用这套理论来设计、分析、优化电路——这是一件非常幸运的事。

计算机选择二进制不是偶然的。它是工程约束(容易实现)、物理特性(抗干扰)和数学工具(布尔代数)三者共同作用的结果。


位和字节——信息的基本单位

一个二进制位称为 1 bit(比特),它只能表示 0 或 1。

显然,单个 bit 能表示的信息太少了。

于是我们把 8 个 bit 组合在一起,称为 1 byte(字节)。

一个字节能表示多少种不同的值?

每个 bit 有 2 种选择(0 或 1),8 个 bit 的组合数是:

2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 = 28 = 256

即从 00000000(十进制 0)到 11111111(十进制 255),共 256 个不同的值。

字节数可表示的数值范围常见用途
1 字节 (8 bit)0 ~ 255一个 ASCII 字符、RGB 颜色中的一个通道值
2 字节 (16 bit)0 ~ 65,535端口号、早期 CPU 的寄存器大小
4 字节 (32 bit)0 ~ 4,294,967,295IPv4 地址、int 类型
8 字节 (64 bit)0 ~ 约 1.8 x 1019现代 CPU 的字长、long 类型

交互演示:一个字节的灯泡模拟器

下面这个交互面板让你直观感受 8 个 bit 如何组合出 0 到 255 之间的任意数值。

每个灯泡代表一个 bit。点击灯泡即可切换 0/1 状态,右侧实时显示对应的十进制数值。

灯泡模拟器:一个字节 = 8 位

点击灯泡切换状态,观察二进制如何映射到十进制。

十进制:0
二进制:00000000

仔细看每个灯泡下方的权重标注。

最左边的灯泡权重最大(128),最右边的权重最小(1)。

这就是「按权展开」的思想——每个位置上的数值乘以它的权重,全部加起来就是最终结果。


用代码理解二进制

Python 内置了对二进制的支持,我们可以直接用它来验证上面的灯泡演示。

实例

# 二进制的基本操作(runoob 演示)

# 1. 查看一个数字的二进制表示
print("十进制 → 二进制:")
for n in [0, 1, 2, 7, 8, 15, 16, 42, 65, 97, 127, 255]:
    # bin() 返回 '0b...' 格式,用 [2:] 去掉前缀
    # zfill(8) 补齐到 8 位
    print(f"  {n:3d} → {bin(n)[2:].zfill(8)}")

print()

# 2. 从二进制字符串解析为十进制
print("二进制 → 十进制:")
binary_strings = ["00000000", "01000001", "01100001", "11111111"]
for b in binary_strings:
    # int(string, 2) 将二进制字符串转为整数
    dec = int(b, 2)
    print(f"  {b} → {dec:3d}")

print()

# 3. 验证:一个字节正好 256 个值
print("一个字节的范围:")
print(f"  最小值: {int('00000000', 2)}")
print(f"  最大值: {int('11111111', 2)}")
print(f"  总个数: {int('11111111', 2) - int('00000000', 2) + 1}")

print()

# 4. 位操作:按位与、或、左移、右移
print("位运算示例:")
a = 0b0011  # 3
b = 0b0101  # 5
print(f"  {bin(a)} & {bin(b)} = {bin(a & b)}  (按位与)")
print(f"  {bin(a)} | {bin(b)} = {bin(a | b)}  (按位或)")
print(f"  {bin(a)} << 1      = {bin(a << 1)}  (左移1位,相当于乘以2)")
print(f"  {bin(b)} >> 1      = {bin(b >> 1)}  (右移1位,相当于除以2)")

print()

# 5. RUNOOB 测试字符串
text = "RUNOOB"
print(f"字符串 '{text}' 每个字符的二进制表示:")
for ch in text:
    ascii_val = ord(ch)
    print(f"  '{ch}' → ASCII={ascii_val:3d} → 二进制={bin(ascii_val)[2:].zfill(8)}")

为什么二进制是「信息表示」的基础

理解了二进制,你就理解了一个关键事实:

计算机内部的一切——数字、文字、图片、声音、视频——最终都以 0 和 1 的形式存储和处理。

后续几讲中你会看到:

  • 第 2 讲:如何在不同进制间转换
  • 第 3 讲:负数如何在二进制中表示(补码)
  • 第 4 讲:小数如何在二进制中表示(浮点数)
  • 第 5 讲:文字如何在二进制中表示(字符编码)

这些内容都建立在「一切皆为 0 和 1」这个基础上。

本模块全部 5 讲的最核心结论:计算机不是「理解」了信息,而是通过精巧的编码规则,把世间万物都映射成了 0 和 1 的组合。