二進位制的定義
人類發明0,1,2,3,4,5,6,7,8,9
這10個數字,大概率是因為我們有十個手指。假如我們把這種計數方式稱為十進位制計數法,然後我們來到了一個世界,那裡面的人只有2個手指。我們該如何用十進位制的思想去用創造出二進位制呢。
簡單約定一下,後面用下標表示進位制,比如\(10_2\)表示二進位制,而\(10_{10}\)表示十進位制。
首先,我們能用的數字只有0,1
這2個,忘掉十進位制中其餘的數字。那麼我們如何計數呢?以數蘋果為例,在十進位制中,我們數到第\(9_{10}\)個蘋果的時候,我們需要做一個操作就是進位,然後低位置為0
。現在來到二進位制,我們如何表示下面蘋果的數量:
需要注意的是,二進位制中只有0,1
,當我們數到第\(1_2\)個蘋果的時候,我們需要做的也是進位。類似地,我們會得到\(10_2\),繼續數下去,就是\(11_2\),所以答案就是這裡有\(11_2\)個蘋果。
對於一個十進位制數,我們知道它有個位
,十位
,百位
,千位
,萬位
……,其實這些位
代表的就是\(10^n\)。比如個位
是\(10^0\),十位
是\(10^1\),百位
是\(10^2\),對於一個數\(123_{10}\),我們可以說它的個位是3
,十位是2
,百位是1
,那麼我們可以通過這樣計算來得到:
於是,對於十進位制,我們可以抽象出下面的公式:
那麼,對於二進位制,我們自然而然可以得到下面的公式(需要注意的是,下面公式右邊的10
其實是\(10_2\)):
公式右邊的10
我們稱之為基底
,十進位制的基低是\(10_{10}\),二進位制的基低是\(10_{2}\)。
二進位制轉十進位制
對於二進位制,我們已經得到這樣的公式:
由於二進位制中的0,1
和十進位制中的0,1
的含義是一樣的,並且二進位制中的\(10_2\)等價於十進位制中的\(2_{10}\),而\(x_i\)(公式右側)在二進位制中只有可能是0,1
,所以我們可以作如下推導:
於是我們可以用十進位制的方式去表達二進位制:
我們可以驗證一下:
所以二進位制的\(11_2\)等價於十進位制的\(3_{10}\),他們都表示上圖中蘋果的數量。
二進位制的加法運算
二進位制的加減法運算,也可以用十進位制的思想來做,首先通過上面例子我們知道\(1_2\)個蘋果加上\(1_2\)個蘋果等於\(10_2\)個蘋果,也就是說在二進位制中1+1=10
。基於這個條件,我們分別來計算1001+0101
和1011+0111
。
首先看1001+0101
,我們列出下面的式子,然後用十進位制加法的思想去做,可以得到結果是1110
:
然後來看1011+0111
,我們也可以列出下面的式子,用同樣的方法去做,但是這邊最後發生了進位,所以結果是10010
:
我們可以轉成十進位制來驗算一下,結果是沒問題的。那麼減法也可以用類似的思想來做。
計算機中二進位制的表示
由於二進位制只能由0,1
組成,那麼對於\(n\)位的二進位制數,我們有\(2^n\)中組合:從\(000...0\)到\(111...1\)。所以一個\(n\)位二進位制數的表示範圍是\(0 \to 2^n\)(這裡的\(2^n\)是十進位制)。
那麼如何表示負數呢?可能有人會說前面加個-
號,和我們平時表示的方式一樣。
其實通過前面的課程我們知道,我們用電路的通斷來表示1
或者0
,電路連通的時候為1
,斷開的時候為0
,只有這兩種狀態,沒有第三種。所以-
號其實是無法在計算機中表示出來的。
為此,前輩們想出了有符號數
,即把二進位制的第一位拿出來作為符號位,1
表示負數,0
表示正數,剩下的來表示具體的數值。
但是如果負數僅僅用第一位符號位來指示,可能還會遇到很多麻煩:比我們知道十進位制中\((-3)+3=0\),這時候我們轉化為4位的二進位制(第一位為符號位)可以得到\(1011_2+0011_2\),結果是\(1011_2+0011_2=1110_2\),如果\(1110_2\)我們仍然把第一位解釋成符號位,那麼轉換成十進位制,就得到了\((-3)+3=-6\),這顯然是不對的。
那麼如何讓\(1011_2+0011_2=0000_2\)呢?在上面加法的例子中,我們還記得\(1011+0111=10010\),這裡發生了進位,也就是2個四位數的二進位制相加,得到一個五位數的二進位制數。那麼在計算機中,假如我們設計的計算機只能表示4位的二進位制數,那麼最終的結果也只能有4位,也就是在該計算機中,我們會得到\(1011+0111=0010\)(最高位1丟棄了)。
基於這個特性,我們可以這樣設計負的二進位制數,假設這裡計算機只能表示4位二進位制數,並且\(0011_2\)的負數設為\(x\),我們需要得到\(0011_2+x=0000_2\),又因為該計算機只能表示4位數,所以在該計算機中,\(0000_2=10000_2\),注意後面是一個5位二進位制數。所以,我們可以這樣去設計\(x\),使得\(0011_2+x=10000_2\),得到\(x=1101\)。我們再來驗算一下:\(0011_2+1101_2=10000_2 \Rightarrow 0000_2\),於是我們可以說,在該計算機中\(0011_2+1101_2=0000_2\)是成立的。
補碼
上面這種二進位制的表示法,我們就稱之為補碼表示法。
總結一下,可以得到如下的定義(假設計算機能表示的二進位制數為\(n\)位):
最高位的含義
我們現在知道了補碼的定義,那麼在補碼中,任何符號位為0
的整數都能得到符號位為1
的負數嗎?我們可以簡單證明一下:
假設有\(n\)位的二進位制數\(x_nx_{n-1}x_{n-2}x_{n-3}...x_2x_1\),且最高位為符號位,所以其數值部分為\(x_{n-1}x_{n-2}x_{n-3}...x_2x_1\)。我們設\(x_{n-1}x_{n-2}x_{n-3}...x_2x_1\)為\(t\),那麼\(-t\)可以表示為\(2^n-t\),而\(2^n \Rightarrow 100...0\left(n個0\right)\),所以我們可以列出下面的式子:
我們設結果為\(r_{n+1}r_nr_{n-1}r_{n-2}r_{n-3}...r_2r_1\),當\(t\)不為0的時候,不管是哪一位不為0,我們做減法的時候肯定會向前借位,但是因為\(2^n\)只有第\(n+1\)位為1,所以只能向前傳遞,借第\(n+1\)位的1。但是因為\(t\)中的\(n+1\)位恆為0,所以我們可以得到\(r_{n+1}=0\),同理\(r_{n}=1\)。所以對於任意的符號位為0
的正數,其補碼都是符號位為1
的負數。
這裡面有個特殊情況,對於0
來說,是不分正負的,而且\(0+0=0\),那麼0
到底是+0
還是-0
呢,也就是說0
的最高位應該是什麼?
我們先來看+0
,由於+0
所有位都是0
,所以\((+0)+(+0)=(+0)\),是沒有問題的。但是對於-0
來說就不是這樣了,由於-0
的最高位為1
,所以當\((-0)+(-0)\)之後,最高位變成了0,並且發生了進位,並且進位被丟棄(前面講過),於是我們得到\((-0)+(-0)=(+0)\),這顯然不太對,直覺告訴我們應該用+0
來表示0
。
那麼當最高位為1,其餘位都是0的時候,這個數字代表什麼呢?
還記得我們得出補碼的過程嗎,我們是用\(2^n-x\)算出來的。那麼對於最高位為1的\(n位\)二進位制數來說,其我們可以用十進位制數\(2^{n-1}\)來表示他的值,通過計算\(2^n-2^{n-1}\)我們可以得到他的正數表示也是\(2^{n-1}\),所以當一個\(n\)位二進位制數的最高位為1,其餘位全是0的時候,他的值就是\(\left(-2^{n-1}\right)\)。
以一個4位二進位制數為例:
正數 | 負數 |
---|---|
0 0000 | |
1 0001 | 1111 -1 |
2 0010 | 1110 -2 |
3 0011 | 1101 -3 |
4 0100 | 1100 -4 |
5 0101 | 1011 -5 |
6 0110 | 1010 -6 |
7 0111 | 1001 -7 |
1000 -8 |
用加法代替減法
前面補碼的定義可知,一個\(n\)位的二進位制正數\(x\)的負數我們可以用\(x_補 \Rightarrow 2^n - x\)來表示。假如我們要計算\(t-x\),我們可以作如下推斷:
那麼當\(x\)是負數的時候呢?類似地,我們可以得到:
這裡的\(|x|\)表示\(x\)的絕對值,我們知道,當\(x\)為負數的時候,其絕對值就是他的補碼。
綜上所述,不論\(x\)是正的還是負的,我們都可以用其補碼來實現用加法代替減法的操作。
總結
最高位作為符號位是一個很巧妙的設計,對於\(n\)位的二進位制數\(x_nx_{n-1}x_{n-2}x_{n-3}...x_1x_0\)來說,他們的數值部分都是\(x_{n-1}x_{n-2}x_{n-2}...x_1x_0\),相當於正好把取值範圍一分為二,一半給了正數,一半給了負數。
補碼的引入也非常合理,最高位不僅可以作為符號位表示數字的正負,並且也可以參與計算、實現用加法代替減法。