進位制轉換指南:二進位、十六進位、八進位完整解析
如果你曾經盯著像 #1A2B3C 這樣的十六進位色碼,或是像 chmod 755 這樣的 Unix 權限設定,好奇這些數字到底從何而來,那你並不孤單。進位制是大多數開發者每天都在使用卻鮮少深思的基礎概念——直到某天真的需要在不同進位之間轉換時才會意識到它的重要性。
讓我們來解決這個問題。本指南將帶你深入了解程式設計中重要的數字系統、如何在它們之間進行轉換,以及各個進位制在實務中的應用場景。
「進位」到底是什麼意思?
我們之所以使用十進位(base-10)計數,是因為我們有十根手指。每個數位代表 10 的一個冪次:
4 2 7
| | |
| | └── 7 × 10⁰ = 7
| └────── 2 × 10¹ = 20
└────────── 4 × 10² = 400
───
Total = 427
這就是位值記數法。「進位」(也稱為基數,radix)告訴你這個系統中有多少個不同的數字符號,以及每個位置的乘數。十進位有 0–9 這些數字,二進位有 0–1,十六進位則有 0–9 和 A–F。
這個概念在所有進位制中完全相同——唯一不同的是可用符號的數量和每個位置的乘數。
趣味小知識:巴比倫人使用的是六十進位(sexagesimal)。這就是為什麼一分鐘有 60 秒、一個圓有 360 度的原因。
二進位(Base-2):硬體的語言
為什麼電腦使用二進位
電腦靠電晶體運作,而電晶體有兩個穩定的狀態:開和關。這完美地對應到 1 和 0。理論上你可以建造一台三進位電腦,但要區分三種電壓位準比區分兩種更難且更容易出錯。二進位之所以勝出,是因為它既簡單又可靠。
如何讀取二進位數字
二進位的運作方式與十進位相同,只不過每個位置代表的是 2 的冪次:
1 0 1 1 0 1
| | | | | |
| | | | | └── 1 × 2⁰ = 1
| | | | └────── 0 × 2¹ = 0
| | | └────────── 1 × 2² = 4
| | └────────────── 1 × 2³ = 8
| └────────────────── 0 × 2⁴ = 0
└────────────────────── 1 × 2⁵ = 32
──
Total = 45
所以二進位的 101101 等於十進位的 45。你從右往左讀,每個位值翻倍:1、2、4、8、16、32、64、128⋯⋯
位元、半位元組與位元組
- 位元(Bit):一個二進位數字(0 或 1)
- 半位元組(Nibble):4 個位元(代表一個十六進位數字,值為 0–15)
- 位元組(Byte):8 個位元(值為 0–255)
- 千位元組(Kilobyte):1,024 個位元組(2¹⁰)
一個位元組可以表示 256 種不同的值,這就是為什麼 ASCII 字元可以用一個位元組表示,而 RGB 色彩通道的範圍是 0 到 255。
二進位算術基礎
二進位的加法規則與十進位相同,只不過在 2 時進位,而非 10:
1 0 1 1 (11 in decimal)
+ 0 1 1 0 ( 6 in decimal)
─────────
1 0 0 0 1 (17 in decimal)
當二進位中 1 + 1 = 10 時(就像十進位中 9 + 1 = 10),你寫下 0 然後進位 1。
八進位(Base-8):歷史遺留的系統
簡短的歷史回顧
八進位在 1960 至 70 年代相當流行,當時的機器如 PDP-8 使用 12 位元字組——恰好可以整除為四組三位元。每個八進位數字恰好對應三個二進位數字,因此成為了方便的簡寫方式。
至今仍會看到八進位的地方
現今最常見的用途是 Unix 檔案權限。當你輸入 chmod 755 script.sh 時,每個數字都是一個八進位數字,分別代表讀取(4)、寫入(2)和執行(1)權限:
7 = 4 + 2 + 1 = rwx (owner: read, write, execute)
5 = 4 + 0 + 1 = r-x (group: read, execute)
5 = 4 + 0 + 1 = r-x (others: read, execute)
程式語言中的八進位數字使用 0o 前綴(或者在 C 語言中僅用前導 0,這已經造成了不少 bug):
const permissions = 0o755; // 493 in decimal
console.log(permissions.toString(8)); // "755"
在 JavaScript 和 Python 中要特別注意:像 0755 這樣的前導零在某些情境下可能會被解讀為八進位。請務必使用明確的 0o 前綴以避免歧義。
十六進位(Base-16):開發者的最愛
為什麼十六進位會存在
十六進位解決了一個實際問題:二進位數字很快就會變得很長。十進位的 255 在二進位中是 11111111——八個數字。而用十六進位表示只需要 FF。每個十六進位數字恰好對應四個二進位數字(一個半位元組),讓轉換變得直觀,數字也更加精簡。
十六進位使用 0–9 加上字母 A–F:
| Decimal | Binary | Hex |
|---|---|---|
| 0 | 0000 | 0 |
| 1 | 0001 | 1 |
| 9 | 1001 | 9 |
| 10 | 1010 | A |
| 11 | 1011 | B |
| 15 | 1111 | F |
十六進位在實際應用中的身影
網頁色彩是十六進位最常見的應用。#FF5733 的拆解如下:
#FF5733
││││││
││││└┘── Blue: 0x33 = 51
││└┘──── Green: 0x57 = 87
└┘────── Red: 0xFF = 255
記憶體位址在除錯器中以十六進位顯示:0x7FFF5FBFFA10 比它的十進位等值 140,734,799,804,944 更容易閱讀。
MAC 位址使用以冒號分隔的十六進位配對:A4:83:E7:2B:00:1F。
CSS 中的色彩:rgba(255, 87, 51, 1.0) 和 #FF5733 代表同一個顏色——十六進位只是更加簡潔。
進位制之間的轉換
十進位轉二進位
反覆除以 2 並收集餘數,從下往上讀取:
45 ÷ 2 = 22 remainder 1 ↑
22 ÷ 2 = 11 remainder 0 │
11 ÷ 2 = 5 remainder 1 │ Read upward:
5 ÷ 2 = 2 remainder 1 │ 101101
2 ÷ 2 = 1 remainder 0 │
1 ÷ 2 = 0 remainder 1 │
結果:十進位的 45 = 二進位的 101101。
十進位轉十六進位
方法相同,但改為除以 16:
427 ÷ 16 = 26 remainder 11 (B) ↑
26 ÷ 16 = 1 remainder 10 (A) │ Read upward: 1AB
1 ÷ 16 = 0 remainder 1 │
結果:十進位的 427 = 十六進位的 1AB。
二進位轉十六進位(最簡單的轉換)
將二進位數字從右往左每四位分為一組,然後分別轉換每組:
Binary: 10 1101
Padded: 0010 1101
Groups: 2 D
Result: 0x2D
驗證:0x2D = 2×16 + 13 = 45 ✓
這就是為什麼十六進位和二進位是天然的搭檔——轉換過程完全是機械式的。
十六進位轉二進位
反向操作。將每個十六進位數字展開為四位二進位數字:
Hex: F A 3
Binary: 1111 1010 0011
Result: 111110100011
小技巧:記住 0–F 的二進位對照表(總共只有 16 個)。一旦記住了,十六進位和二進位之間的轉換就能在腦中瞬間完成。先從二的冪次開始記:1=0001、2=0010、4=0100、8=1000。
程式語言中的進位表示法
每一種主流語言都有用不同進位撰寫數字的語法:
// JavaScript
const binary = 0b101101; // 45
const octal = 0o55; // 45
const hex = 0x2D; // 45
const decimal = 45; // 45
// Convert to string in any base
(45).toString(2); // "101101"
(45).toString(8); // "55"
(45).toString(16); // "2d"
// Parse from string
parseInt("101101", 2); // 45
parseInt("55", 8); // 45
parseInt("2D", 16); // 45
# Python
binary = 0b101101 # 45
octal = 0o55 # 45
hexval = 0x2D # 45
# Convert to string
bin(45) # '0b101101'
oct(45) # '0o55'
hex(45) # '0x2d'
# Parse from string
int("101101", 2) # 45
int("55", 8) # 45
int("2D", 16) # 45
// C / C++
int binary = 0b101101; // 45 (C23 / GCC extension)
int octal = 055; // 45 (leading zero = octal!)
int hex = 0x2D; // 45
注意 C 語言的陷阱:前導 0 代表八進位。寫 int x = 010; 得到的是 8,而不是 10。這已經讓無數程式設計師栽了跟頭。
實際應用場景
位元運算與旗標
十六進位是位元遮罩的標準表示法,因為每個數字恰好涵蓋四個旗標:
const READ = 0x01; // 0001
const WRITE = 0x02; // 0010
const EXECUTE = 0x04; // 0100
const ADMIN = 0x08; // 1000
let permissions = READ | WRITE; // 0x03 = 0011
if (permissions & EXECUTE) {
// check if execute bit is set
}
除錯與記憶體檢查
當你在位址 0xDEADBEEF 看到記憶體區段錯誤,或使用 0xCAFEBABE 初始化記憶體時,這些都是特意選擇的十六進位常數,因為它們在記憶體傾印中特別容易辨識。Java 的 class 檔案就以魔術數字 0xCAFEBABE 開頭——沒錯,當初取這個名字的人確實玩得很開心。
網路協定
IPv6 位址使用十六進位表示法:2001:0db8:85a3:0000:0000:8a2e:0370:7334。MAC 位址、USB 供應商 ID 和藍牙 UUID 都使用十六進位表示,因為它讓二進位資料既精簡又易讀。
親自動手試試
省去手動計算的麻煩。我們的進位轉換器可以即時處理任意進位之間的轉換——十進位、二進位、八進位、十六進位,或任何最高到 36 的自訂進位。只需貼上數字,選擇來源和目標進位,即可立即獲得結果。所有運算都在你的瀏覽器中完成,不會將任何資料傳送到伺服器。
它在以下情境中特別實用:
- 將十六進位記憶體傾印轉換為十進位以便除錯
- 以二進位/八進位計算 Unix 權限
- 在十六進位和 RGB 值之間驗證色碼
- 在非二的冪次的進位之間進行轉換
相關資源
- Base64 編碼解析 — Base64 使用不同的方法(將 6 位元群組對應到 64 個字元)將二進位編碼為文字
- 雜湊演算法比較 — 雜湊輸出通常以十六進位顯示
- 進位轉換器 — 在瀏覽器中即時轉換任意進位
🛠️ 立即試用:進位轉換器 — 在二進位、八進位、十進位、十六進位以及任何最高到 36 的進位之間自由轉換。100% 瀏覽器端運算,完全免費。