關於二進位世界的秘密

2021-01-08 SegmentFault思否

我們都知道,計算機的底層都是使用二進位數據進行數據流傳輸的,那麼為什麼會使用二進位表示計算機呢?或者說,什麼是二進位數呢?在拓展一步,如何使用二進位進行加減乘除?二進位數如何表示負數呢?本文將 一一 為你揭曉。

為什麼用二進位表示

我們大家知道,計算機內部是由 IC 電子元件組成的,其中CPU 和內存也是 IC 電子元件的一種,CPU 和內存圖如下

CPU

內存

CPU 和內存使用 IC 電子元件作為基本單元,IC 電子元件有不同種形狀,但是其內部的組成單元稱為一個個的引腳。

有人說 CPU 和內存內部都是超大規模集成電路,其實 IC 就是集成電路(Integrated Circuit)。

IC元件切面圖

IC 元件兩側排列的四方形塊就是引腳,IC 的所有引腳,只有兩種電壓: 0V 和 5V,IC 的這種特性,也就決定了計算機的信息處理只能用 0 和 1 表示,也就是二進位來處理。

一個引腳可以表示一個 0 或 1 ,所以二進位的表示方式就變成 0、1、10、11、100、101 等,雖然二進位數並不是專門為引腳來設計的,但是和 IC 引腳的特性非常吻合。

計算機的最小集成單位為位,也就是比特(bit),二進位數的位數一般為 8位、16位、32位、64位,也就是 8 的倍數,為什麼要跟 8 扯上關係呢?

因為在計算機中,把 8 位二進位數稱為一個字節, 一個字節有 8 位,也就是由 8 個 bit 構成。

為什麼 1 個字節等於 8 位呢?因為 8 位能夠涵蓋所有的字符編碼,這個記住就可以了。

字節是最基本的計量單位,位是最小單位。

用字節處理數據時,如果數字小於存儲數據的字節數 ( = 二進位的位數),那麼高位就用 0 填補,高位和數學的數字表示是一樣的,左側表示高位,右側表示低位。

比如 這個六位數用二進位數來表示就是 100111,只有 6 位,高位需要用 0 填充,填充完後是00100111,佔一個字節,如果用 16 位表示 就是 0000 0000 0010 0111 佔用兩個字節。

我們一般口述的 32 位和 64 位的計算機一般就指的是處理位數,32 位一次可以表示 4 個字節,64 位一次可以表示 8 個字節的二進位數。

我們一般在軟體開發中用十進位數表示的邏輯運算等,也會被計算機轉換為二進位數處理。對於二進位數,計算機不會區分他是 圖片、音頻文件還是數字,這些都是一些數據的結合體。

什麼是二進位數

那麼什麼是二進位數呢?為了說明這個問題,我們先把00100111 這個數轉換為十進位數看一下,二進位數轉換為十進位數,直接將各位置上的值 * 位權即可,那麼我們將上面的數值進行轉換

二進位轉十進位表示圖

也就是說,二進位數代表的 00100111 轉換成十進位就是 39,這個 39 並不是 3 和 9 兩個數字連著寫,而是 3 * 10 + 9 * 1,這裡面的 10 , 1 就是位權,以此類推,上述例子中的位權從高位到低位依次就是 7 6 5 4 3 2 1 0。

這個位權也叫做次冪,那麼最高位就是 2 的 7 次冪,2 的 6 次冪等等。二進位數的運算每次都會以 2 為底,這個 2 指得就是基數,那麼十進位數的基數也就是 10 。

在任何情況下位權的值都是數的位數 - 1,那麼第一位的位權就是 1 - 1 = 0, 第二位的位權就睡 2 - 1 = 1,以此類推。

那麼我們所說的二進位數其實就是 用 0 和 1 兩個數字來表示的數,它的基數為 2,它的數值就是每個數的位數 * 位權再求和得到的結果,我們一般來說數值指的就是十進位數,那麼它的數值就是 3 * 10 + 9 * 1 = 39。

移位運算和乘除的關係

在了解過二進位之後,下面我們來看一下二進位的運算,和十進位數一樣,加減乘除也適用於二進位數,只要注意逢 2 進位即可。二進位數的運算,也是電腦程式所特有的運算,因此了解二進位的運算是必須要掌握的。

首先我們來介紹移位運算,移位運算是指將二進位的數值的各個位置上的元素坐左移和右移操作,見下圖

移位過程

上述例子中還是以 39 為例,我們先把十進位的 39 轉換為二進位的 0010 0111,然後向左移位 <<一個字節,也就變成了 0100 1110,那麼再把此二進位數轉換為十進位數就是上面的 78,十進位的 78 竟然是十進位 39 的 2 倍關係。

我們在讓 0010 0111 左移兩位,也就是 1001 1100,得出來的值是 156,相當於擴大了四倍!

因此你可以得出來此結論,左移相當於是數值擴大的操作,那麼右移 >>呢?按理說右移應該是縮小 1/2,1/4 倍,但是 39 縮小二倍和四倍不就變成小數了嗎?這個怎麼表示呢?請看下一節

便於計算機處理的補數

剛才我們沒有介紹右移的情況,是因為右移之後空出來的高位數值,有 0 和 1 兩種形式。要想區分什麼時候補 0 什麼時候補 1,首先就需要掌握二進位數表示負數的方法。

二進位數中表示負數值時,一般會把最高位作為符號來使用,因此我們把這個最高位當作符號位。

符號位是 0 時表示正數,是 1 時表示負數。那麼 -1 用二進位數該如何表示呢?

可能很多人會這麼認為:因為 1 的二進位數是 0000 0001,最高位是符號位,所以正確的表示 -1 應該是 1000 0001,但是這個答案真的對嗎?

計算機世界中是沒有減法的,計算機在做減法的時候其實就是在做加法,也就是用加法來實現的減法運算。比如 100 - 50 ,其實計算機來看的時候應該是 100 + (-50),為此,在表示負數的時候就要用到二進位補數,補數就是用正數來表示的負數。

為了獲得補數,我們需要將二進位的各數位的數值全部取反,然後再將結果 + 1 即可,先記住這個結論,下面我們來演示一下。

-1 取反過程

具體來說,就是需要先獲取某個數值的二進位數,然後對二進位數的每一位做取反操作(0 ---> 1 , 1 ---> 0),最後再對取反後的數 +1 ,這樣就完成了補數的獲取。

補數的獲取,雖然直觀上不易理解,但是邏輯上卻非常嚴謹,比如我們來看一下 1 - 1 的這個過程,我們先用上面的這個 1000 0001(它是 1 的補數,不知道的請看上文,正確性先不管,只是用來做一下計算)來表示一下

1 - 1 分析圖

奇怪,1 - 1 會變成 130 ,而不是 0,所以可以得出結論 1000 0001 表示 -1 是完全錯誤的。

那么正確的該如何表示呢?其實我們上面已經給出結果了,那就是 1111 1111,來論證一下它的正確性

1 - 1 正確的分析圖

我們可以看到 1 - 1 其實實際上就是 1 + (-1),對 -1 進行上面的取反 + 1 後變為 1111 1111, 然後與 1 進行加法運算,得到的結果是九位的 1 0000 0000,結果發生了溢出,計算機會直接忽略掉溢出位,也就是直接拋掉 最高位 1 ,變為 0000 0000。

也就是 0,結果正確,所以 1111 1111 表示的就是 -1 。

所以負數的二進位表示就是先求其補數,補數的求解過程就是對原始數值的二進位數各位取反,然後將結果 +1,當然,結果不為 0 的運算同樣也可以通過補數求得正確的結果。

不過,有一點需要注意,當運算結果為負的時候,計算結果的值也是以補數的形式出現的,比如 3 - 5 這個運算,來看一下解析過程

3 - 5 的解析過程

3 - 5 的運算,我們按著上面的思路來過一遍,計算出來的結果是 1111 1110,我們知道,這個數值肯定表示負數,但是負數無法直接用十進位表示,需要對其取反+ 1,算出來的結果是 2,因為 1111 1110的高位是 1,所以最終的結果是 -2。

程式語言的數據類型中,有的可以處理負數,有的不可以。比如 C 語言中不能處理負數的 unsigned short 類型,也有能處理負數的 short 類型 ,都是兩個字節的變量,它們都有 2 的十六次冪種值,但是取值範圍不一樣,short 類型的取值範圍是 -32768 - 32767 , unsigned short 的取值範圍是 0 - 65536。

仔細思考一下補數的機制,就能明白 -32768 比 32767 多一個數的原因了,最高位是 0 的正數有 0 ~ 32767 共 32768 個,其中包括 0。最高位是 1 的負數,有 -1 ~ -32768 共 32768 個,其中不包含 0。0 雖然既不是正數也不是負數,但是考慮到其符號位,就將其歸為了正數。

算數右移和邏輯右移的區別

在了解完補數後,我們重新考慮一下右移這個議題,右移在移位後空出來的最高位有兩種情況 0 和 1。當二進位數的值表示圖形模式而非數值時,移位後需要在最高位補 0,類似於霓虹燈向右平移的效果,這就被稱為邏輯右移。

邏輯右移示意圖

將二進位數作為帶符號的數值進行右移運算時,移位後需要在最高位填充移位前符號位的值( 0 或 1 )。這就被稱為算數右移。如果數值使用補數表示的負數值,那麼右移後在空出來的最高位補 1,就可以正確的表示 1/2,1/4,1/8 等的數值運算。如果是正數,那麼直接在空出來的位置補 0 即可。

下面來看一個右移的例子。將 -4 右移兩位,來各自看一下移位示意圖

邏輯右移和算數右移示意圖

如上圖所示,在邏輯右移的情況下, -4 右移兩位會變成 63, 顯然不是它的 1/4,所以不能使用邏輯右移,那麼算數右移的情況下,右移兩位會變為 -1,顯然是它的 1/4,故而採用算數右移。

那麼我們可以得出來一個結論:左移時,無論是圖形還是數值,移位後,只需要將低位補 0 即可;右移時,需要根據情況判斷是邏輯右移還是算數右移。

下面介紹一下符號擴展:將數據進行符號擴展是為了產生一個位數加倍、但數值大小不變的結果,以滿足有些指令對操作數位數的要求,例如倍長於除數的被除數,再如將數據位數加長以減少計算過程中的誤差。

以 8 位二進位為例,符號擴展就是指在保持值不變的前提下將其轉換成為 16 位和 32 位的二進位數。

將 0111 1111 這個正的 8 位二進位數轉換成為 16 位二進位數時,很容易就能夠得出 0000 0000 0111 1111 這個正確的結果,但是像 1111 1111這樣的補數來表示的數值,該如何處理?

直接將其表示成為 1111 1111 1111 1111 就可以了。也就是說,不管正數還是補數表示的負數,只需要將 0 和 1 填充高位即可。

邏輯運算的竅門

掌握邏輯和運算的區別是:將二進位數表示的信息作為四則運算的數值來處理就是算數,像圖形那樣,將數值處理為單純的 0 和 1 的羅列就是邏輯。

計算機能夠處理的運算,大體可分為邏輯運算和算數運算,算數運算指的是加減乘除四則運算;邏輯運算指的是對二進位各個數位的 0 和 1 分別進行處理的運算,包括邏輯非(NOT 運算)、邏輯與(AND 運算)、邏輯或(OR 運算)和邏輯異或(XOR 運算)四種。

邏輯非:指的是將 0 變成 1,1 變成 0 的取反操作

邏輯與:指的是"兩個都是 1 時,運算結果才是 1,其他情況下是 0"

邏輯或:指的是"至少有一方是 1 時,運算結果為 1,其他情況下運算結果都是 0"

邏輯異或:指的是"其中一方是 1,另一方是 0 時運算結果才是 1,其他情況下是 0"

與或非異或真值表

掌握邏輯運算的竅門,就是要摒棄二進位數表示數值這一個想法。大家不要把二進位數表示的值當作數值,應該把它看成是 開關上的 ON/OFF。

文章參考:《程序是怎樣跑起來的》

相關焦點

  • 關於二進位、十進位、八進位、十六進位數據轉換計算方法詳細總結
    (1)十進位轉換為八進位 十進位轉換成八進位有兩種方法: 1)間接法:先將十進位轉換成二進位,然後將二進位又轉換成八進位 2)直接法:前面我們講過,八進位是由二進位衍生而來的,因此我們可以採用與十進位轉換為二進位相類似的方法,還是整數部分的轉換和小數部分的轉換
  • 二進位轉換為十進位和十進位轉換為二進位的方法
    各位小夥伴們大家好,在之前的文章中小編也介紹了關於二進位轉十進位的方法,這次小編知道了一個更簡單的方法,具體如下:比如我們要把28轉為二進位:28轉換為2進位先用2的n次方來表示28這個數,然後用2的n次方乘以1或者乘以0,相加來湊成與之相等的數,得到的1或者是0,根據這個表格,從左往右把二進位數字湊在一起,11100就是28的二進位了。
  • 為何人類都用十進位計數?關於二進位,八進位……你又了解多少?
    十進位就這樣一代傳一代逐漸被整個人類社會使用。實際上,在古代世界獨立開發的有文字的計數體系中,除了巴比倫文明的楔形數字為60進位,瑪雅數字為20進位外,幾乎全部為十進位。二進位——計算機的計數進位我們知道計算機是不懂人類的語言的,那如何讓計算機按照人的想法工作呢?
  • python進位轉換:十進位轉二進位的用法
    我們在學習python時候肯定會碰到關於進位轉換,其實這是非常簡單的,這個就像小學學習數學乘法口訣意義,只要記住轉換口訣即可輕鬆應用,一起來看下具體的操作內容吧~一、python進位轉換dec(十進位)—> bin(二進位)dec(十進位)—>
  • 計算機的語言——二進位,十進位、八進位、十六進位與二進位之間的轉換
  • 二進位、八進位、十進位與十六進位
    例如對於二進位來說,該規則是「滿二進一,借一當二」;對於十進位來說,該規則是「滿十進一,借一當十」。其他進位也是這樣。A 8)16訣竅:因為每四位二進位數對應一位十六進位數,所以,以小數點為界,整數位則將二進位數從右向左每4位一隔開,不足4位的在左邊用0填補即可;小數位則將二進位數從左向右每4位一隔開,不足4位的在右邊用0填補即可。
  • 二進位轉換十進位,十進位轉換二進位
    如果把一個十進位的數轉換成二進位的數 , 直接把數除 以二 , 餘數為一就寫1 , 整除 , 就寫0 , 一直除完為止
  • EV3關於10進位轉換2進位的詳解
    哈咯各位大家好之前突發奇想想做一個關於十進位轉化成二進位的想法,在這裡給大家講解一下。關於數字有多進位的,十進位、二進位、三進位、八進位、十六進位....等等。對我們最熟悉的莫過於十進位和二進位了,接下來給大家講解下如何實現將十進位轉化為二進位。
  • 二進位、十進位和十六進位
    二進位就是逢二進位,它的一個位只有兩個值:0 和 1,但它卻是實現計算機系統的最基本的理論基礎,計算機(包括單片機)晶片是基於成萬上億個的開關管組合而成的,他們每一個都只能有開和關兩種狀態,再難找出第三個狀態了(不要辯解半開半關這個狀態,它是不穩定態,是極力避免的),所以他們只能對應於二進位的 1 和 0 兩個值,而沒有 2、3、4......,理解二進位對於理解計算機的本質很有幫助。
  • 進位轉換 二進位轉十進位
    上節課我們學習了十進位轉換成二進位的方法,那二進位轉換十進位是怎麼轉換的呢?
  • 二進位的前身是八卦?一起走進10000000000的世界
    不過這還不是計算機語言的最終形態,我們平常寫的程序、敲的代碼,各種數據,在電腦運行識別時,都被編譯器翻譯成了二進位!當再把二進位拆解、計算、重建,就有了我們生活中的軟體、遊戲、音樂、電影、app......也許,擁有了二進位,就擁有了全世界?小謝爾頓夢中奇遇的二元宇宙二進位到底是個什麼?
  • 進位詳解:二進位、八進位和十六進位
    二進位我們不妨將思維拓展一下,既然可以用 0~9 共十個數字來表示數值,那麼也可以用0、1兩個數字來表示數值,這就是二進位(Binary)。例如,數字 0、1、10、111、100、1000001 都是有效的二進位。在計算機內部,數據都是以二進位的形式存儲的,二進位是學習編程必須掌握的基礎。本節我們先講解二進位的概念,下節講解數據在內存中的存儲,讓大家學以致用。
  • 二進位,八進位,十進位,十六進位之間的轉換
    什麼是二進位二進位是計算技術中廣泛採用的一種數制。二進位數據是用0和1兩個數碼來表示的數。它的基數為2,進位規則是「逢二進一」,借位規則是「借一當二」,由18世紀德國數理哲學大師萊布尼茲發現。當前的計算機系統使用的基本上是二進位系統,數據在計算機中主要是以補碼的形式存儲的。
  • 計算機基礎進位轉換(二進位、八進位、十進位、十六進位)
    1.十進位轉R進位1.1 十進位轉二進位十進位整數轉二進位十進位整數轉換成二進位採用「除2倒取餘」,十進位小數轉換成二進位小數採用
  • scratch+程小奔機器人實現「進位轉換」(十進位轉二進位)
    進位轉換圖【原創】文章全部內容皆為作者原創,如有轉載請註明出處我們人類有十根手指,通常情況下我們在生活中的計數方式為「十進位」(即0-9),也就說滿十進一;而在計算機的世界裡,基礎電路只有「開/關(通/斷)」(即0/1)兩種情況,這與誕生幾千年的二進位不謀而合;例如:二進位數字110,表達的就是十進位中的6;二進位數字1111,表達的就是十進位中的15。
  • 二進位,八進位,十進位,十六進位轉換詳解~
    ①、數碼:用來表示進位數的元素。                                二進位:0,1。                                八進位:0,1,2,3,4,5,6,7                                十進位:0,1,2,3,4,5,6,7,8,9。
  • 程式設計師的情商:二進位電腦能識別,十進位人易懂,十六進位能做啥
    計算機專業的同學,在學習編程中,尤其是初學者,經常有這樣的疑問,一般人只認識十進位(520),電腦只能識別二進位(1000001001),那十六進位(208)能做什麼的?為什麼還要在中間加上一個十六進位呢,是不是多此一舉嗎?本來初學編程,對二進位就不熟悉,要花不少時間和理解來學習理解,在學個十六進位不是很多餘嗎?
  • 萊布尼茨發明二進位與太極八卦無關
    關於二進位數學算法的「中國緋聞」也不是什麼空穴來風。一提到關於中國古代科學技術的「緋聞」,人們總是聯想到這方面的大家李.約瑟。可是「0、1的中國緋聞」到真不是這位老兄煽呼起來的。那麼,令「博大精深粉」追捧的葉下香風從何而來呢?
  • 二進位、八進位、十進位、十六進位之間的轉換
    反過來,當我們看到 FD時,如何迅速將它轉換為二進位數呢?先轉換F:        看到F,我們需知道它是15(可能你還不熟悉A~F這六個數),然後15如何用8421湊呢?應該是8 + 4 + 2 + 1,所以四位全為1 :1111。接著轉換 D:        看到D,知道它是13,13如何用8421湊呢?
  • 二進位與八進位互相轉換
    上節課我們學習了二進位轉換十進位,那二進位與常用的八進位之間是如何互相轉換的呢?下面我們先看看二進位與八進位的轉換方法。