電腦怎麼用0和1計算?二進位與加法電路
電腦把電壓的高、低這2種狀態當成「1」和「0」,所有數字都用0和1的排列(二進位)來表示。計算則是組合許多小電路來進行:輸入0和1,就會輸出固定的0和1。這種小電路稱為邏輯閘。例如加法,只要用AND、XOR、OR這3種邏輯閘就能做出來。
這篇文章可以了解
- 電腦不用10種狀態,而用0和1這2種的理由
- 十進位和二進位的轉換方法(13 ↔ 1101),以及位元、位元組的意思
- 組合邏輯閘來做加法的電路(半加器、全加器)
- 負數的表示方法(二補數),以及減法、乘法都能用加法做出來
先備知識:不需要。如果知道電晶體是「用電切換的小開關」,會比較容易閱讀。
生活中的例子
在手機的計算機App按「6+7」,馬上就會出現「13」。照片裡排著數百萬個彩色的點,訊息裡排著一個個中文字。這些數字、顏色和文字,在手機裡全都是以0和1的排列來記住和計算的。
可是,明明只有0和1,要怎麼表示13,又怎麼把6和7相加呢?這篇文章會從數字的表示方法開始,一路看到做加法的電路內部。
為什麼只用0和1這2種
電腦零件的核心,是稱為電晶體的小開關。開關會切換讓電通過或不通過。在電路中,這會變成電壓的「高」和「低」。這2種狀態,就約定稱為「1」和「0」。
你可能會想,那把電壓分成10個等級,直接表示0~9的數字不就好了?可是,電路的電壓會受到其他配線的影響和溫度等因素,一直有些微的晃動。分成10個等級,相鄰等級的差距就變小,晃動時容易讀錯。
如果只有「高」和「低」2種,兩者之間就能留出很大的空隙。稍微晃動,也幾乎不會讀錯。晃動到多大還不會讀錯的餘裕,稱為雜訊邊限。要讓數十億個開關一個都不讀錯地運作,這種確實性不可或缺。開關的原理,在「電晶體是什麼?」中說明。
用二進位來數數
平常寫數字的方法,是使用10個數字(0~9)的「十進位」。在十進位中,從右邊起是個位、十位、百位,每往左1位,位的大小(位值)就變成10倍。例如345,意思是3個100、4個10、5個1。
只用0和1這2個數字來寫數的方法,稱為「二進位」。原理和十進位相同,不同的是位值。二進位從右邊起是1、2、4、8、16,每往左1位就變成2倍。每一位不是0就是1,所以表示的是那一位的位值「要用」還是「不用」。
從二進位到十進位:1101是13
把二進位轉成十進位,只要把是1的位的位值加起來。以1101來說,從左邊起,位值8的位是1,位值4的位是1,位值2的位是0,位值1的位是1。8+4+1,就是13。
從十進位到二進位:13是1101
反過來,要把13轉成二進位,就重複「除以2,記下餘數」。
- 13÷2=6 餘1(位值1的位)
- 6÷2=3 餘0(位值2的位)
- 3÷2=1 餘1(位值4的位)
- 1÷2=0 餘1(位值8的位)
商變成0就結束。把餘數從下往上排,就是1101。因為第1個餘數是位值1的位,下一個是位值2的位,是從右邊的位依序決定的。想用其他數字試試看的人,可以用進位轉換與二補數工具確認答案。
位元與位元組
二進位的1位,也就是一個0或1,稱為「位元」(bit)。這是英文binary digit(二進位的位數)的縮寫。1個位元能表示的,只有0和1這2種。
位元每增加1個,能表示的排列方式就變成2倍。2個位元是00、01、10、11這4種,3個位元是8種。4個位元是16種,能表示0到15。
在電腦中,8個位元合成一組,稱為「1位元組」(byte)。8個位元的排列方式,是2乘8次的256種。所以1位元組能表示0到255的整數。記憶體和儲存空間的「GB」,也是以位元組為單位的量。
用手算算看二進位的加法
二進位的加法,也和十進位的直式計算一樣,從右邊的位依序相加。1位和1位的加法,只有下面4種。
- 0+0=0
- 0+1=1、1+0=1
- 1+1=10(二進位的「10」就是2。這一位是0,再往上一位送1)
這就和十進位的9+1變成10,往上一位送1一樣。這種「往上一位送1」,稱為進位。在二進位中,1+1馬上就會進位。
舉例來說,用4位的二進位計算6+7。為了湊成4位,在左邊補0,6是0110,7是0111。
| 位值8 | 位值4 | 位值2 | 位值1 | |
|---|---|---|---|---|
| 從下一位來的進位 | 1 | 1 | 0 | — |
| 6 | 0 | 1 | 1 | 0 |
| 7 | 0 | 1 | 1 | 1 |
| 答案 | 1 | 1 | 0 | 1 |
位值1的位是0+1=1。位值2的位是1+1=10,所以寫0並進位。位值4的位是1+1再加上進位的1,等於11,寫1後再進位。位值8的位是0+0+1=1。答案1101,就像前面看到的,是13。
做加法的電路:半加器
接下來,把這個加法做成電路。材料是「邏輯閘」。這是輸入0和1後,依固定規則輸出0或1的小電路,用數個到十幾個電晶體連接而成。這裡使用下面3種。
- AND:2個輸入都是1時,才輸出1
- OR:輸入中只要有1個是1,就輸出1
- XOR:2個輸入不同時(只有一方是1時),輸出1
把要相加的2個1位數設為A、B,把前面4種加法做成表。列出輸入的所有組合,以及當時輸出的表,稱為真值表。1列代表1種組合。最後一列的意思是,1+1的答案是「進位1、和0」,也就是10。
| A | B | 進位 | 和(這一位的答案) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 0 |
「和」這一欄,只有A和B不同時才是1。這正是XOR的規則。「進位」這一欄,只有兩者都是1時才是1,是AND的規則。也就是說,只要並排1個XOR和1個AND,就能做出1位加法的電路。這稱為「半加器」。
連進位也一起加:全加器
半加器能把2個數的1位相加。但是,像6+7位值4的位那樣,從第2位起,還必須一起加上從下一位來的進位。把3個1位數(A、B、從下一位來的進位)相加,輸出和與往上的進位的電路,稱為全加器。
全加器的功能,可以換句話說成「用二進位回答3個輸入中有幾個1」。輸入的組合有8種,但依1的個數整理,真值表就是下面4列。
| 輸入中1的個數 | 進位 | 和 |
|---|---|---|
| 0個 | 0 | 0 |
| 1個 | 0 | 1 |
| 2個 | 1 | 0 |
| 3個 | 1 | 1 |
6+7位值4的位,是1、1和進位的1,共有3個1。就像表的最後一列,結果是進位1、和1。全加器可以用2個半加器和1個OR閘做出來。先用第1個半加器把A和B相加,再用第2個半加器把那個和與下一位來的進位相加。2個半加器中只要有一個產生進位,OR閘就讓往上的進位變成1。在邏輯電路模擬器中,可以載入半加器和全加器的範例,切換開關確認運作。
把全加器排起來,幾位數都能加
依位數把全加器橫向排列,把每個進位輸出,接到上一位的全加器。這樣就成為幾位數都能相加的電路。4位就用4個全加器,64位就用64個。下圖是用這個電路,計算前面的6+7的情形。
這種排法,進位會從低位往高位,像漣漪(英文是ripple)一樣依序傳遞。所以稱為漣波進位加法器。構造很簡單,但高位要等到下面的進位傳來,答案才會確定。64位的話,最壞要等64級。
所以實際的CPU,會用提前算出進位等更快的方法。幾種方法的差異,整理在「漣波進位、先行進位、進位保留加法器的差異」的表格中。
另外,電路的位數是固定的。用4位的電路計算9+8,答案17(10001)有5位。最上面的1放不進去,答案變成0001,也就是1。這稱為「溢位」(overflow),有時會成為程式錯誤的原因。
負數的表示方法:二補數
因為只有0和1,「−」號也必須用0和1來表示。現在幾乎所有的電腦,都用二補數這個方法表示負整數。以4位(4位元)來說明,就是把最左邊那一位的位值,規定為「−8」而不是「8」的方法。
按照這個規定,1101是−8+4+0+1,等於−3。0111是+7,1000是−8,1111是−1。4位元能表示−8到+7共16種。同樣是1101,用不使用負數的規定(無號)來讀,就是13。是哪一種意思,不是由位元的排列決定,而是由程式怎麼讀來決定。
| 4位元的排列 | 以無號來讀 | 以二補數來讀 |
|---|---|---|
| 0111 | 7 | 7 |
| 0011 | 3 | 3 |
| 0000 | 0 | 0 |
| 1111 | 15 | −1 |
| 1101 | 13 | −3 |
| 1000 | 8 | −8 |
要把一個數的正負號反過來,就把所有位的0和1對調,再加1。以3(0011)為例,對調後是1100,加1是1101,就是−3。
這個方法的好處,是前面的加法電路可以直接使用。計算5+(−3),0101+1101=10010。和9+8時一樣,第5位的1放不進4位元的電路。剩下的是0010,也就是2,和5−3=2相符。在二補數中,丟掉這個1,就會得到正確的答案。
減法和乘法,也能用加法做出來
使用二補數,減法就變成「加上負數」。要計算A−B,只要把B的0和1對調、加1後,再加到A上就好。對調是NOT閘(把0和1反過來的邏輯閘)的工作。加1則只要把輸入到位值1那個全加器的進位設為1就能做到。這樣,1個加法電路就能同時做加法和減法。
乘法要用到移動位數的操作。在十進位中,在數字右邊加1個0,就變成10倍。同樣地,在二進位中,把整體往左移1位、右邊補0,就變成2倍。這個操作稱為「位移」。
例如6×5,因為5是4+1,所以是6×4和6×1的和。把6(110)移2位,變成11000,也就是24,再加上110(6),得到11110,也就是30。二進位的乘法,可以用「移位」和「相加」的反覆來計算。位移的運作,可以用位元運算計算工具確認。
不過,這裡的說明為了呈現原理,做了簡化。實際的CPU有專用電路,能把乘法途中的數一次加起來,比一次加一個快得多。
文字和顏色,也用數字表示
文字是替每個字決定號碼,再把號碼用二進位記住。這種號碼的規定稱為「字元編碼」。在1963年訂出第1版的ASCII字元編碼中,英文字母「A」是65號,用7個位元表示是1000001。
中文字也有號碼。在替全世界文字編號的Unicode中,「中」是20013號。在常用的儲存格式(UTF-8)中,「中」用3個位元組來記住。
顏色是用數字,分別表示光的三原色紅、綠、藍(RGB)的亮度。常用的格式中,每種顏色用8個位元(0~255的256個等級)表示。組合是256×256×256,約1,678萬色。照片就是把這些顏色的數字,依畫面的點數排列起來。
常見的誤解
誤解:1是有電流流動的狀態,0是沒有電流的狀態
實際上,0和1不是用有沒有電流來區分,而是用電壓「高」或「低」來區分。在現在的晶片電路中,不論是持續輸出1,還是持續輸出0,幾乎都沒有電流流動。電流主要是在0和1切換的瞬間流動。這個誤解,容易來自「開關的開、關」這種說法。
誤解:二進位的位數多,所以效率差
實際上,位數多是事實。100萬用十進位是7位,用二進位要20位。即使如此,每1位的電路非常簡單,能確實又快速地運作,所以整體來說二進位比較有利。另外,在想增加記憶量的場合,也會使用多於2種的等級。例如TLC型的快閃記憶體,在1個記憶單位中把電壓分成8個等級,記住3個位元。相對地,等級之間的空隙變窄,在速度和可改寫次數上,比只記1個位元的方式不利。
誤解:「1KB」永遠是1,000位元組
實際上,算法有2種。千(k)本來是1,000倍的意思。另一方面,在電腦中,也有把接近1,000的1,024(2乘10次的數)算成1KB的習慣。為了區分,IEC(國際電工委員會)在1998年決定,把1,024位元組稱為「KiB」(kibibyte)。不過,現在兩者仍常常都寫成「KB」。對手機容量顯示的影響,在「記憶體和儲存空間有什麼不同?」中說明。
從數字來看
| 位元數 | 能表示的排列方式 | 比較 |
|---|---|---|
| 1位元 | 2種 | 0或1 |
| 4位元 | 16種 | 0~15,或−8~+7 |
| 8位元(1位元組) | 256種 | 0~255 |
| 24位元(RGB各8位元) | 約1,678萬種 | 畫面上1個點的顏色 |
| 32位元 | 約43億種 | 十進位10位 |
| 64位元 | 約1,845京種 | 十進位20位 |
位元每增加1個,能表示的排列方式就變成2倍。10位元是1,024種,20位元約105萬種,30位元約10億7千萬種。記住每增加10位元,大約變成1,000倍,會很方便。「1KB是1,024位元組」的算法,也是從這裡來的。另外,現在電腦和手機的CPU,大多能用1個指令把64位元的數相加。
進一步學習
- 用表格看差異:定點數與浮點數的差異(小數的表示方法)、組合邏輯電路與循序邏輯電路的差異(負責計算的電路,和負責記住的電路)
- 下一步的名詞:先行進位加法器(提前算出進位)、算術位移(移動負數時)、位元運算(在程式中直接處理位元)
- 用圖來看:NOT閘用2個電晶體做成的原理,可以在圖解「CMOS反相器」中看到
- 接著閱讀:用這個加法電路來執行指令的零件,就是「CPU是什麼?」