一、前置知识:计算机如何表示负号?
计算机里没有 - 这个符号。它的做法是:用二进制最高位当符号位。
- 0 开头 → 正数
- 1 开头 → 负数
考试和教学默认使用 8 位二进制(即 1 字节)来表示一个数。原理和 16 位、32 位、64 位完全一样,只是位数多少的区别。
关于位和字节
初学者常把 bit 和 byte 搞混,这里先澄清:
| 概念 | 符号 | 关系 |
|---|---|---|
| 位(比特) | bit | 最小单位,一个 0 或 1 |
| 字节 | byte | 1 byte = 8 bit |
Java 中常见数据类型的大小:
| 类型 | 字节数 | 位数 |
|---|---|---|
| byte | 1 | 8 |
| short | 2 | 16 |
| int | 4 | 32 |
| long | 8 | 64 |
所以 int 是 4 字节 = 32 位,不是 4 位。考试用 8 位出题,纯粹是为了手算方便。
二、三种编码方式
以 +5 和 -5 为例,逐步拆解。
2.1 原码
规则:
- 正数:符号位
0+ 绝对值的二进制 - 负数:符号位
1+ 绝对值的二进制
+5 的原码:0 0000101
↑ ───────
正 5 的二进制
-5 的原码:1 0000101
↑ ───────
负 5 的二进制(只有符号位不同)
原码最直观,人一眼就能看懂数值。但原码直接参与运算会出错(后面会详细解释),所以需要反码和补码。
2.2 反码
规则:
- 正数的反码 = 原码(不变)
- 负数的反码 = 符号位不动,其余位取反(0 变 1,1 变 0)
+5 的反码:0 0000101(和原码一样)
-5 的原码:1 0000101
-5 的反码:1 1111010
↑ ───────
不动 每一位都反过来
反码本身并不能直接用于正确运算,它是一个过渡产物,目的是为了推导出补码。
2.3 补码
规则:
- 正数的补码 = 原码(不变)
- 负数的补码 = 反码 + 1
-5 的反码:1 1111010
+ 1
-5 的补码:1 1111011
补码是计算机中真正存储和运算使用的编码。
2.4 完整对照表
| +5 | -5 | |
|---|---|---|
| 原码 | 0 0000101 | 1 0000101 |
| 反码 | 0 0000101 | 1 1111010 |
| 补码 | 0 0000101 | 1 1111011 |
2.5 一句话记忆
正数:原码 = 反码 = 补码,不用动
负数:原码 → 反码(取反)→ 补码(加 1)
三、考试常考的坑:补码的范围
| 编码 | 8 位表示范围 |
|---|---|
| 原码 | -127 ~ +127 |
| 补码 | -128 ~ +127 |
为什么补码能多表示一个 -128?
- 原码中
00000000表示 +0,10000000表示 -0,两个编码对应同一个值 0,浪费了一个位置。 - 补码中
00000000是唯一表示 0 的编码,而10000000被定义为 -128,没有浪费。
四、为什么需要反码和补码?
这是理解整个体系最关键的问题。
4.1 原码做加法会出错
计算机没有减法器,只能做加法。5 - 3 在计算机里要变成 5 + (-3)。
用原码直接相加:
5 的原码:00000101
-3 的原码:10000011
00000101
+ 10000011
----------
10001000 → 原码解读为 -8
5 + (-3) = -8? 明显错了。
原码的加法器不知道最高位是符号位,它把所有位一视同仁地相加,结果就是错的。要让原码正确运算,需要一套复杂的逻辑:
- 判断两个数的符号
- 符号不同时,比较绝对值大小
- 用大的减小的
- 确定结果的符号
每一步都需要额外的电路——比较器、减法器、符号判断逻辑——又多又贵。
4.2 补码做加法直接正确
换成补码:
5 的补码:00000101
-3 的补码:11111101
00000101
+11111101
---------
100000010
8 位装不下,最高位的 1 溢出丢掉,剩下 00000010 = 2。
5 + (-3) = 2,正确。
同一套加法电路,不加任何额外逻辑,正数负数一起算,结果自动正确。
4.3 对比总结
原码表示负数
→ 加法器算不对
→ 需要:符号判断 + 比较器 + 减法器 + 符号修正
→ 电路复杂,成本高
补码表示负数
→ 加法器直接算就对了
→ 只需要:一套加法电路
→ 电路简单,成本低
五、补码的数学原理(进阶理解)
用时钟来类比
时钟指向 3 点,想调到 10 点:
- 方式一:顺时针拨 7 格 → 3 + 7 = 10
- 方式二:逆时针拨 5 格 → 3 - 5 = 10(绕一圈回来)
减 5 和加 7 效果一样,因为时钟是 12 进制,-5 和 +7 在模 12 下等价。
二进制同理
8 位二进制能表示 256 个数(0~255),相当于一个 模 256 的时钟。
在模 256 的世界里:
-3 和 +253 等价,因为 (-3) mod 256 = 253
验证:-3 的补码是 11111101,把它当无符号数看 = 128+64+32+16+8+4+1 = 253。
补码的本质:用"绕一圈"的方式,把负数变成了一个正数的等价表示,减法就变成了加法。
这是数学上模运算的自然结果,计算机工程师只是把这个性质用到了电路设计里。
六、计算机电路是怎么工作的(进阶理解)
最底层只有三种门电路
| 门 | 行为 |
|---|---|
| AND(与门) | 两个都是 1,输出 1 |
| OR(或门) | 只要有一个 1,输出 1 |
| NOT(非门) | 输入 1 输出 0,输入 0 输出 1 |
用这三种门就能搭出一切数字电路。
加法器的搭建
一位加法的真值表:
| 输入 A | 输入 B | 进位 | 结果 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 0 |
用 AND 门和 XOR(异或)门就能实现,叫做半加器。把 8 个半加器串起来,就得到一个 8 位加法器。
这就是为什么补码如此重要——它让这一套加法电路既能算加法又能算减法,不需要额外的减法器和比较器。
七、速查卡片
┌─────────────────────────────────────┐
│ 正数:原码 = 反码 = 补码 │
│ 负数:原码 → 取反得反码 → +1得补码 │
│ 逆推:补码 → -1得反码 → 取反得原码 │
│ │
│ 补码范围(8位):-128 ~ +127 │
│ 原码范围(8位):-127 ~ +127 │
│ │
│ 核心意义:减法变加法,简化电路设计 │
└─────────────────────────────────────┘