為什麼要先複習進制與補數#

在學習編寫系統程式之前,進制間的轉換與補數系統是必備的基本技能。現今電腦多採用「二進位 + 二補數(Two’s Complement)」儲存資料,所以這一章先把基礎打穩,後續學位元操作、浮點數、組合語言時才不會卡關。

讀完本章你會掌握:

  • 計算機如何儲存資料
  • 計算機如何處理負數與減法
  • 進制間的轉換手法

進制系統#

進位制是一種記數方式,利用有限種數字符號來表示所有數值。一種進位制中可以使用的數字符號數目稱為「基數」或「底數」。若一個進位制的基數為 n,即稱為 n 進位制。現今最常用的是十進位(基數 10)。

以十進位數字 28 為例:

10 進制2 進位8 進位16 進位
2811100341C

2 進制#

遇到 2 就進位:

10 進制2 進制
0000
1001
2010
3011
4100
5101
6110
7111

8 進制#

遇到 8 就進位:

10 進制8 進制
77
810
911
1012

16 進制#

16 進制系統可以使用 0 - 15 表達數值,但 10 - 15 本身已經是進位過後的結果,因此用英文字母 A-F 取代:

10 進制16 進制
99
10A
11B
12C
13D
14E
15F
1610

進制轉換#

8 進制轉 2 進制#

8 進制中,1 個位元可以表示 8 種狀態;二進位需要 3 個位元才能表示 8 種狀態。把 8 進制的單一位元轉為 2 進制的 3 個位元即可:

34 (8) -> 011 100 -> 11100 (2) -> 28 (10)

16 進制轉 2 進制#

16 進制中,1 個位元可以表示 16 種狀態;二進位需要 4 個位元才能表示 16 種狀態。把 16 進制的單一位元轉為 2 進制的 4 個位元:

1C (16) -> 0001 1100 -> 11100 (2) -> 28 (10)

n 進制與 10 進制的相互轉換#

若要把二進位 10011.011 轉為十進位,整數部分按權位展開即可,小數部分則用負次方權位展開。

從十進位轉到 n 進位的技巧:

  • 整數部份採用以 n 為除數的連除法,直到商小於除數為止,答案取所有餘數(從下往上讀)。
  • 小數部份採用以 n 為乘數的連乘法,直到積等於零為止,答案取所有「進位」。若積數無法至 0,則需取到指定的位數(位數越多越精確)。

補數系統#

1’s 補數(一的補數)#

將二進位數按位元逐個反轉,就得到 1’s 補數(ones’ complement)。

0001 (+1) 的一補數為 1110 (-1)

2 進制無號數有號數一補數
0000000
0001111
0111777
10008-0-7
10019-1-6
111014-6-1
111115-7-0

1’s 補數加法#

一補數的特性可以讓加法電路同時運算減法:

0001 (1) + 1100 (-3) = 1101 (-2)

2’s 補數(二的補數)#

不論是「有號數直接表示」或「一補數」,都會產生 +0-0 兩種零的狀態。為了避免這個問題,電腦科學家進一步發展出二補數(Two’s Complement)。它的計算規則非常簡單:

  • MSB(最高位元)權重為負數
  • 其餘位元權重為正數
  • 任何數字的二補數 = 一補數 + 1

範例#

-7 為例。先把 -7 寫成一補數:

1000

接著一補數 +1 得到二補數:

1001

利用「MSB 為負,其餘為正」的權重規則驗算:

-8 (MSB)421 (LSB)
1001

(-8) × 1 + 4 × 0 + 2 × 0 + 1 × 1 = -7,結果一致。

二補數最大的好處:只有一個零、加減法電路統一、且最高位元同時是符號位,硬體實作非常乾淨。這也是為什麼現代電腦幾乎都採用二補數來表示有號整數。

小結#

  • 二進位是計算機運作的基礎,但人類在閱讀記憶體 dump 或位址時通常會以 8 / 16 進位表示,因為它們與二進位有對應關係(每位 = 3 / 4 個 bit)。
  • 補數系統解決了「如何用同一套電路同時做加法與減法」的問題;其中二補數又解決了一補數中 ±0 並存的問題。

原文出處#

  • 原書/iThome:https://ithelp.ithome.com.tw/articles/10264829