Learning Objectives
- 說明位元與位元組,以及 n 個位元可以表示 2ⁿ 種不同的值
- 用權重加總把二進位換成十進位,用「除以 2 取餘數」把十進位換成二進位
- 用 4 位一組、3 位一組,在二進位與十六進位、八進位之間互換
- 分辨以 1000 為單位的 KB、MB、GB 與以 1024 為單位的 KiB、MiB、GiB
為什麼 1 TB 的硬碟只剩 931 GB
買了一顆標示 1 TB 的外接硬碟,接上 Windows 電腦,檔案總管卻顯示大約 931 GB。少掉的 69 GB 跑去哪裡了?
答案是:沒有少。硬碟廠商和作業系統用了兩種不同的「1 GB」。要看懂這件事,得先知道電腦怎麼表示數字。
這一課要回答:
- 電腦裡只有 0 與 1,怎麼表示 37、255 這些數字?
- 二進位、十進位、八進位、十六進位怎麼互相轉換?
- KB、MB、GB 到底是 1000 還是 1024?
位元與位元組
電腦內部用電路的兩種狀態(例如電壓高、電壓低)表示資料,記成 1 和 0。一個 0 或 1 叫做一個位元(bit,binary digit 的縮寫)。
一個位元只有兩種可能。多放幾個位元,組合就倍增:
| 位元數 | 組合數 | 例子 |
|---|---|---|
| 1 | 2¹ = 2 | 0、1 |
| 2 | 2² = 4 | 00、01、10、11 |
| 3 | 2³ = 8 | 000 到 111 |
| 8 | 2⁸ = 256 | 0000 0000 到 1111 1111 |
| 16 | 2¹⁶ = 65,536 | |
| 32 | 2³² ≈ 43 億 |
規則很簡單:n 個位元有 2ⁿ 種組合,每多一個位元,組合數就乘以 2。
8 個位元合稱一個位元組(byte),是電腦存放資料的基本單位。一個位元組可以表示 256 種值,例如 0 到 255 的整數。檔案大小、記憶體容量都以位元組計算。
位值記數法:每一位都有權重
我們平常用的十進位,每一位代表 10 的某次方:
3 4 5
│ │ └─ 5 × 10⁰ = 5
│ └────── 4 × 10¹ = 40
└─────────── 3 × 10² = 300
───
345
二進位用一模一樣的規則,只是每一位的權重(weight)換成 2 的次方,而且每一位只能是 0 或 1:
位元 1 0 1 1 0 1
權重 32 16 8 4 2 1 (2⁵ 2⁴ 2³ 2² 2¹ 2⁰)
── ── ── ──
32 + 8 + 4 + 1 = 45
所以二進位 101101 就是十進位的 45。二進位轉十進位:把是 1 的那些位的權重加起來。
寫法上,為了分清楚是哪一種進位,常寫成 101101₂、45₁₀,程式語言裡則用前綴:0b101101(二進位)、0o55(八進位)、0x2D(十六進位)。
二進位轉十進位:權重加總
從最右邊那一位開始,權重是 1;每往左一位,權重乘以 2。是 1 的位就把權重加進總和。注意 ▲ 是由右往左移動的。
十進位轉二進位:除以 2 取餘數
反過來,要把 37 換成二進位,可以一直除以 2,記下每一次的餘數:
37 ÷ 2 = 18 餘 1 ← 第 0 位(最低位)
18 ÷ 2 = 9 餘 0
9 ÷ 2 = 4 餘 1
4 ÷ 2 = 2 餘 0
2 ÷ 2 = 1 餘 0
1 ÷ 2 = 0 餘 1 ← 最高位
商變成 0 就停下來,餘數由下往上讀:100101。驗算:32 + 4 + 1 = 37。
為什麼可行?除以 2 的餘數就是這個數「最右邊那一位」是 0 還是 1;除完之後,等於把整個數往右移一位,下一次的餘數就是原本的下一位。
十進位轉二進位:一步一步除
n % 2 是除以 2 的餘數,n // 2 是商(整數除法)。看 binary 怎麼從右往左一位一位長出來。你可以在下方把 37 改成別的數(例如 100 或 255)再跑一次。
八進位與十六進位:把位元分組
二進位很長:255 是 11111111,一個 32 位元的數有 32 個 0 和 1,人很難讀。所以常把位元分組,改用十六進位(hexadecimal)或八進位(octal)來寫:
- 十六進位每一位有 16 種可能(0~9,再用 A~F 代表 10~15),剛好等於 4 個位元(2⁴ = 16)
- 八進位每一位有 8 種可能(0~7),剛好等於 3 個位元(2³ = 8)
| 十進位 | 二進位 | 八進位 | 十六進位 |
|---|---|---|---|
| 0 | 0000 | 0 | 0 |
| 7 | 0111 | 7 | 7 |
| 8 | 1000 | 10 | 8 |
| 9 | 1001 | 11 | 9 |
| 10 | 1010 | 12 | A |
| 11 | 1011 | 13 | B |
| 12 | 1100 | 14 | C |
| 13 | 1101 | 15 | D |
| 14 | 1110 | 16 | E |
| 15 | 1111 | 17 | F |
換算時從右邊開始分組,每一組各自換成一個數字:
二進位 0010 1111 10 101 111
十六進位 2 F = 0x2F 2 5 7 = 0o257
十六進位轉十進位也是權重加總,權重是 16 的次方:0x2F = 2 × 16 + 15 = 47。
十六進位到處都看得到:網頁顏色 #3C6F9A(紅、綠、藍各 2 個十六進位數字,也就是各 1 個位元組)、網路卡的 MAC 位址、Unicode 字元編號 U+4E2D、程式出錯時印出的記憶體位址。
在 Python 裡可以直接轉換:bin(47) 得到 '0b101111',hex(47) 得到 '0x2f',oct(47) 得到 '0o57',int('2F', 16) 得到 47。
KB、MB、GB:1000 還是 1024
因為電腦以二進位運作,記憶體的大小天生是 2 的次方。2¹⁰ = 1024 很接近 1000,早年就把 1024 位元組叫做 1 KB,1024 KB 叫 1 MB,一路用下來。
但 kilo、mega、giga 在國際單位制裡明明是 1000、100 萬、10 億。為了消除混淆,國際電工委員會(IEC)在 1998 年訂出另一組二進位前綴:
| 以 1000 為單位(十進位) | 位元組數 | 以 1024 為單位(二進位) | 位元組數 |
|---|---|---|---|
| KB(kilobyte) | 1,000 | KiB(kibibyte) | 1,024 |
| MB(megabyte) | 1,000² | MiB(mebibyte) | 1,024² |
| GB(gigabyte) | 1,000³ | GiB(gibibyte) | 1,024³ |
| TB(terabyte) | 1,000⁴ | TiB(tebibyte) | 1,024⁴ |
實際使用上兩種習慣並存:
- 硬碟、SSD、隨身碟的包裝用十進位:1 TB = 1,000,000,000,000 位元組
- Windows 的檔案總管以 1024 為單位計算,單位卻仍寫成 GB;所以 1 TB 的硬碟顯示約 931 GB(10¹² ÷ 1024³ ≈ 931.3)
- macOS 從 10.6 版起改用十進位顯示,同一顆硬碟顯示約 1 TB
- 記憶體(RAM)的規格習慣以 1024 為單位,「16 GB 記憶體」是 16 × 1024³ 位元組
所以開頭那顆硬碟沒有少容量,只是 931 GiB 被寫成了「931 GB」。看到 KB、MB、GB 時,要看上下文判斷是哪一種。
網路速度用的是「位元」:100 Mbps 是每秒 100 百萬位元,換成位元組要再除以 8,大約每秒 12.5 MB。注意小寫 b 是位元、大寫 B 是位元組。
想一想:二進位與位元組
二進位 1101 是十進位多少?
一個位元組有幾個位元?可以表示幾種不同的值?
下面的 Python 程式會印出什麼?
print(bin(10), hex(255))
想一想:分組與單位
十六進位 A3 換成二進位是多少?
要表示 0 到 999 的每一個整數,至少需要幾個位元?
網頁顏色 #3C6F9A 的前兩個十六進位數字 3C 代表紅色的強度。3C 是十進位多少?
重點整理
- 位元(bit)是一個 0 或 1;8 個位元是一個位元組(byte)。n 個位元有 2ⁿ 種組合,8 個位元可以表示 0~255。
- 位值記數法:每一位有權重。二進位的權重是 2 的次方,二進位轉十進位=把是 1 的位的權重加起來。
- 十進位轉二進位=一直除以 2,餘數由下往上讀。
- 十六進位一位=4 個位元,八進位一位=3 個位元;從右邊開始分組互換。程式裡用
0b、0o、0x前綴。 - KB、MB、GB 依標準是 1000 的次方,KiB、MiB、GiB 是 1024 的次方;硬碟包裝用前者,Windows 以後者計算卻寫成 GB,所以 1 TB 顯示約 931 GB。
下一課:8 個位元能表示 0~255,那負數怎麼辦?127 再加 1 為什麼會變成 -128?第 04 課看整數的表示與溢位。