計算機內部以二進制補碼表示有符號整數,這背後蘊含著巧妙的數學原理。本文從機器數/真值概念入手,詳細推導原碼、反碼、補碼定義與轉換規則,並用同餘理論證明「為何補碼能將減法轉為加法」,最後解釋 int32 範圍 [-2³¹, 2³¹-1] 的由來。
| 數值 | 原碼 | 反碼 | 補碼 |
| +1 | 0000 0001 | 0000 0001 | 0000 0001 |
| -1 | 1000 0001 | 1111 1110 | 1111 1111 |
轉換規則:
- 正數:三碼相同。
- 負數原碼:符號位 1,其餘為絕對值二進制。
- 負數反碼:符號位不變,其餘位取反。
- 負數補碼:反碼 + 1(或原碼取反 + 1)。
三、為何需要反碼與補碼?
1. 原碼缺陷:符號位參與運算導致減法錯誤
1 - 1 = 1 + (-1)
原碼:[00000001] + [10000001] = [10000010] = -2 ❌
硬體電路若辨別符號位再決定加減,設計極其複雜。
2. 反碼修正減法,但引入「±0」問題
反碼:[00000001] + [11111110] = [11111111] = -0 ❌
真值正確,但存在 [00000000]=+0 和 [10000000]=-0 兩個編碼,浪費一個編碼且邏輯不清。
3. 補碼完美解決:唯一 0 編碼 + 多表示一個最小值
補碼:[00000001] + [11111111] = [00000000] = 0 ✅
00000000 唯一表示 0。
10000000 表示 -128(原碼/反碼無法表示)。
- 8 位補碼範圍:[-128, +127],比原/反碼 [-127, +127] 多一個值。
四、數學本質:同餘理論與鐘面模型
1. 同餘定義
a ≡ b (mod m) 意為 a mod m = b mod m。負數取模規則:x mod y = x - y × floor(x/y)。
例:-1 mod 128 = 127,-2 mod 12 = 10。
2. 鐘面類比
12 小時鐘面:
往回撥 2 小時 ≡ 往前撥 10 小時(因 -2 ≡ 10 (mod 12))。
同理,二進制 n 位系統模數 M = 2ⁿ(補碼)或 2ⁿ-1(反碼)。
3. 反碼證明(模 127)
-1 的反碼 11111110 → 去符號位 = 126
-1 ≡ 126 (mod 127)
2 - 1 ≡ 2 + 126 (mod 127) → 結果模 127 同餘 = 1 ✅
4. 補碼證明(模 128)
-1 的補碼 11111111 → 去符號位 = 127
-1 ≡ 127 (mod 128)
2 - 1 ≡ 2 + 127 (mod 128) → 結果模 128 同餘 = 1 ✅
補碼將模數從 127 擴展到 128,故能多表示 -128(對應 10000000)。
五、工程應用:32 位有符號整數範圍
- 最高位為符號位,剩餘 31 位表示數值。
- 補碼編碼下,範圍 [-2³¹, 2³¹-1] = [-2147483648, 2147483647]。
- 最小值
-2147483648 對應補碼 0x80000000,無原碼/反碼表示。
六、總結
- 原碼直觀但不適合硬體運算。
- 反碼修正減法,但有 ±0 問題。
- 補碼基於模運算同餘原理,完美解決 ±0 並多表示一個最小值,成為通用標準。
- 理解同餘與模運算,是掌握計算機算術本質的鑰匙。
- 上一篇文章: 杭電 OJ 2016 經典入門題:數列最小值交換輸出 (C 語言實現)
- 下一篇文章: APUE 進程間通信(IPC)完整實戰:管道、FIFO、XSI IPC(消息隊列、信號量、共享記憶體)
Copyright ©
程式碼之家 All Rights Reserved