3.3 · 二進制運算與溢出
目標: 正確做二進制加減,並在 n 位儲存中檢測溢出。
二進制加法規則
跟十進制一樣,只是僅有 0 和 1:
| A | B | 和 | 進位 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
有趣的是 1 + 1 = 10₂ —— 寫 0,進 1。跟十進制的 5 + 5 = 10 一樣。
例 · 5 + 6(4 位)
進位: 1 1 1
0 1 0 1 (5)
+ 0 1 1 0 (6)
─────────
1 0 1 1 (11)2
3
4
5
結果:1011₂ = 11₁₀。✓
例 · 9 + 7(4 位) —— 溢出!
進位: 1 1 1 1
1 0 0 1 (9)
+ 0 1 1 1 (7)
─────────
1 0 0 0 0 (16,但 5 位)2
3
4
5
4 位裏結果為 0000 加一個進位輸出。該進位就是溢出標誌 —— 見下。
二進制減法
兩種常用方法:
方法 1 · 借位(學校式)
| A | B | 差 | 借 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
1 0 0 1 (9)
− 0 1 0 1 (5)
─────────
0 1 0 0 (4) ✓2
3
4
方法 2 · 加二的補碼
這就是真 CPU 乾的事(見 3.4 二的補碼)。把減數轉成負的形式,然後相加。
A − B = A + (−B)。
什麼是溢出?
溢出發生在算術結果裝不下可用位數時。
對無符號 n 位數,最大可表示值是 2ⁿ − 1。超過就讓結果按 2ⁿ 取模環繞。
| 位數 | 無符號最大值 |
|---|---|
| 4 | 15 |
| 8 | 255 |
| 16 | 65,535 |
| 32 | 4,294,967,295 |
檢測溢出
無符號加法規則
如果加法產生從最高位 (MSB) 溢出的進位 —— 即答案需要額外位,就發生了溢出。
4 位: 9 + 7
進位: 1
1001 (9)
+ 0111 (7)
──────
1 0000 (16 —— 需要 5 位 → 溢出!)2
3
4
5
6
有符號(二的補碼)加法規則
溢出發生在兩個操作數同號但結果異號時。
+5 + +6 用 4 位有符號二的補碼
0101 (+5)
+ 0110 (+6)
──────
1011 (4 位二的補碼下為 -5!)2
3
4
5
兩個操作數都正但結果被解讀為負 → 溢出。
(關於有符號表示的細節見下一節。)
n 位儲存的最小最大值
課程指引明確提到 n 位寄存器能容納的最小與最大數字。
| 位數 | 無符號最小 | 無符號最大 | 有符號最小(二補) | 有符號最大(二補) |
|---|---|---|---|---|
| 4 | 0 | 15 | −8 | +7 |
| 8 | 0 | 255 | −128 | +127 |
| 16 | 0 | 65,535 | −32,768 | +32,767 |
要會推導**最多 16 位(2 位元組)**的情況,課程指引明確點出。
實例
例 A · 8 位無符號 200 + 100
200₁₀ = 1100 1000,100₁₀ = 0110 0100。
1100 1000
+ 0110 0100
-----------
1 0010 1100 ← 9 位 → 溢出(8 位最大為 255)2
3
4
8 位截斷後結果是 00101100 = 44 —— 不是真正的 300。忽略溢出的程序會默默給出 44。
例 B · 4 位有符號 +5 + +6
兩數都能塞進 4 位,但和 11 超過有符號最大 +7。溢出。
例 C · 4 位有符號 −5 + −4
−5 = 1011,−4 = 1100。和 = 1 0111。4 位截斷後是 0111 = +7。兩個輸入都負但結果為正 → 溢出。
練習活動
用 4 位二進制算並標記溢出:
0110 + 01011101 + 0011(無符號)0111 + 0001(有符號)1100 − 00111000 + 1000(有符號)
答案
1011(無溢出)10000→0000+ 進位,無符號溢出1000,有符號 → 溢出(正 + 正 = 負)1001(無溢出)10000→0000,有符號 → 溢出(負 + 負 = 零,符號變了)
溢出的現實影響
- 《文明》遊戲的 Gandhi 核彈 bug —— 他的好戰度從 1 下溢到 255。
- YouTube 瀏覽計數 —— 在 2,147,483,647(有符號 32 位最大)卡住。
- 波音 787 發電機 —— 因 32 位有符號溢出,不能持續供電超過 248 天。
- 網絡安全 —— 許多漏洞(緩衝區溢出攻擊)從算術溢出開始。
學生常見錯誤
- 混淆進位輸出(無符號溢出)與符號改變(有符號溢出)。
- 忘了只要結果裝不下所選寬度,就算數學正確也會溢出。
- 不同位寬相加時沒補齊到統一寬度。
考試式題目
題(4 分): 做以下 8 位無符號二進制加法,説明是否溢出。 (a)
1010 1101 + 0001 0011(b)1111 1000 + 0000 1000
參考答案:
(a) 1010 1101 + 0001 0011 = 1100 0000。無 MSB 進位 → 無溢出。
(b) 1111 1000 + 0000 1000 = 1 0000 0000。從 MSB 進位 → 溢出(正確結果 256 裝不進 8 位)。
關鍵要點
- 二進制加法用與十進制相同的逐列進位思路。
- 溢出 = 結果裝不下所分配的位。
- 無符號溢出 ⇒ MSB 有進位。
- 有符號溢出 ⇒ 兩操作數同號、結果反號。
- n 位無符號最大值為
2ⁿ − 1。
➡️ 下一節:3.4 二的補碼