什麼是二進制#
引言#
我們從小就會數數。
1,2,3,4,5,6,7,8,9,10,11,12 ……
任何一個智力正常的人都能無窮無盡地數下去。
可是你有沒有想過,數字難道就只能是這樣嗎?
接下來,我們換一種數數方法。
1,10,11,100,101,110,111,1000,1001,1010,1011,1100……
你可能有點摸不著頭腦,但這就是剛剛 1~12 在二進制裡的表示。
看完這篇文章,我相信你能徹底理解。
這篇文章從數制寫起,講解了二進制是什麼,為什麼要用二進制,還講解了由 1 和 0 構成的二進制數是怎麼變成我們計算機中的文本、圖片、視頻的。文章挺長,但耐心讀完,我相信你能有所收穫。
數字#
絕大多數人生來有兩雙手,每隻手有五個手指。
當我們還在幼兒時代時,我們就會借助手指來數數了。
人大多數情況下只有十根手指,那麼如果想表示大於十的數,該怎麼辦?
你大概會說:“這不是很簡單嘛,可以用數字啊”
古人也是一樣的想法,因此創造了各種符號用來表示 “數”
現今,我們最常用的是阿拉伯數字。
進制與數字#
進制#
小學老師教過我們,阿拉伯數字是 “滿十進一” 的,即每當數到了 10,就將當前的一位歸零,將下一位加上一。
這就是進制。
滿幾進一,就是幾進制。
比如阿拉伯數字中,當從 0 數到 9 後,下個數字就不再用新的數字表示,而是將十位寫上 1,個位寫上 0,也就是 10,這便是十進制,也是絕大部分人日常使用的進制。
而二進制就是 “滿二進一”,即每當數到了 2,就將當前的一位歸零,將下一位加上一。因此,類似於十進制有 10 個數字,二進制只有兩個數字,0 和 1。
“位” 的意義#
十進制中,對於一個數字中的單個數位,我們有 “個位”、“十位”、“百位”、“千位” 之稱。
其中每個數位,分別代表有多少個, , , ……
如在數字1394
中:
“4” 位於個位上,代表4個(一)
“9” 位於十位上,代表9個(十)
“3” 位於百位上,代表3個(百)
“1” 位於千位上,代表1個(千)
合起來,就是
二進制的道理與之相同。
二進制的每個數位,分別代表, , , ……
如在二進制數字1010
中
第一位的 “0” 代表 0 個
第二位的 “1” 代表 1 個
第三位的 “0” 代表 0 個
第四位的 “1” 代表 1 個
全部加起來,就是
在二進制的部分,你可能注意到我沒有說 “個位”,“十位”,而是說 **“第一位”,“第二位”**,這是因為 “個位”、“十位” 的叫法本身就是對於十進制而言的,因此無法被用於描述二進制的數位,後同。
實踐#
現在讓我們來用十進制和二進制從 1 開始數數,鞏固一下剛剛的知識吧。
-
首先是 1,這個數字在十進制和二進制都是一樣的,略過。
-
接下來,到了十進制的 2,剛剛我們講過,二進制 “滿二進一”,因此我們應該將最低位歸零,並在下一位加一,也就是10。
-
十進制的 3 呢?很簡單,你應該也能想明白,應該是 11。
-
到了十進制的 4,很明顯,再加 1 的話最低位又到了 2。因此將最低位歸零,並將下一位加一。可是下一位本來就是 1 啊,那怎麼辦?很顯然,下一位也應該歸零,再將第三位加一,最終得到100。
這是從 3 數到 4 的整個流程:
第三位 | 第二位 | 最低位 | 描述 |
---|---|---|---|
0 | 1 | 1 | 原來的數 3 |
0 | 1 | 1+1 | 加 1 |
0 | 1+1 | 0 | 發現最低位到 2 了,於是將其歸零,下一位加 1 |
0+1 | 0 | 0 | 下一位也到 2 了,再歸零,再下一位,即第三位加 1 |
1 | 0 | 0 | 最終得到 100 |
總結#
二進制其實沒有那麼難,核心思想就「滿二進一」,只要懂了這個,你也能向平時數數一樣,輕鬆地用二進制數數。
為什麼要用二進制#
我相信,看我文章的,大概都對電腦有一定了解吧。
一種簡單的說法是,計算機的處理器是電路構成的,而電路中,通電(或高電壓,開啟)表示 1,不通電(或低電壓,關閉)表示 0,實現起來很簡單。
並且,在邏輯中,“真”、“假” 兩種狀態也正好可以用 1 和 0 來表示。
二進制在計算機中的具體實現#
引言#
在計算機中,所有的文字、圖片、視屏、網頁、文檔、軟件在計算機眼裡,都只是由 0 和 1 構成的二進制數據。
字節與比特#
計算機中的二進制數據通常以 8 位二進制數來分割,因此8個二進制數字被稱為 1 個字節 ,1 個二進制數字叫 1比特。
編碼#
當我們在處理文本、音頻、圖像等信息時,計算機需要將這些信息轉換成二進制數字進行處理。這個過程稱為編碼。
文字編碼#
簡述#
說起文本在二進制中的表示方法,就不得不提到文字編碼。文字編碼是二進制與文字的對應關係,它可以讓計算機把某個二進制數字轉換為字符,或將字符轉換為二進制數。文字編碼的核心思想並不複雜,就是一個類似於字典的表,計算機在轉換過程中,逐個字符查表即可。
常用的文字編碼有ASCII、GBK、GB2312、Unicode等。
文字編碼的歷史 & 常見的文字編碼#
ASCII#
計算機是美國人發明的,他們發明電腦時,只想過把自己的 26 個英文字母裝進表中,大寫和小寫字母,再加上數字和標點符號(其實還有一些控制字符,比如換行、回車、制表符等),7 位二進制(十進制最大 127)足夠了,又預留了一位,剛好 1 字節(8 位)。多出來的一位,後來被歐洲的那些帶了變音符號的字母占去了。這就是ASCII(美國信息交換標準代碼)。
中文編碼#
計算機傳到了中國,中國人一看,1 字節哪夠裝漢字啊,於是大陸整出了裝簡體字的GB2312,使用兩個字節表達漢字,包括 6763 個常用漢字(包括一級漢字 3755 個,二級漢字 3008 個)。台灣這邊呢,整出了裝繁體字的Big5(大五码),共收錄 13060 個漢字,同樣也用兩個字節表示一個漢字。後來大陸還推出過 GB2312 的 “高級版”GBK,它在 GB2312 的標準上多加了不少生僻字和其它字符,總計有兩萬多個漢字,但同樣以雙字節存儲。
Unicode#
後來,中國有中國的編碼,美國有美國的編碼,日本有日本的編碼,歐洲有歐洲的編碼…… 終於,計算機界的大牛一拍大腿,搞出了Unicode。Unicode 是 uni 前綴(表示 “一”“統一”)和 code(表示編碼)組合而成的詞。這表示 Unicode 的核心理念是包含世界上所有語言的字符,統一所有的編碼,最終成為一個世界通用的編碼。幸運的是,它做到了。截至 2021.09.14 發布的Unicode14.0標準,Unicode 總共包含 144967 個字符,囊括了你見過的沒見過的知道的不知道的有人用的沒人用的…… 各種語言的字符,當然還包括 emoji。
UTF-8(可變長度編碼)#
之前我們說過,中文編碼大多是兩個字節,是因為兩個字節最多可以裝下 65535 個字符,無論是 GB2312 的 6763 個還是 GBK 的兩萬多個都綽綽有餘,但是到了 Unicode 時代,理論上是需要四個字節表示的,但是有聰明人想出了可變長度編碼這個東西。它可以根據不同的字符來保存不同長度的數據,並且能保證計算機能準確分割。比如英文字符用 1 字節,中文用 3 字節,emoji 用 4 字節。(這裡中文多出一個字節是因為可變長度編碼本身需要浪費一定空間,但是比所有字符均用 4 字節好得多)
如果你想知道可變長度編碼具體是如何實現的,請看下表。
Unicode 編碼(十六進制) | UTF-8 字節流(二進制) |
---|---|
000000-00007F | 0xxxxxxx |
000080-00007FF | 110xxxxx 10xxxxxx |
000800-00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
表的左邊是文字的 Unicode 十六進制編碼,右邊是二進制數據,其中 x 表示有實際用處的數據,其餘部分因可變長度編碼的實現機制占用。
之前提到,可變長度編碼的用處是即使每個字符用不同長度的二進制數據保存,計算機仍然能準確地將一大串二進制數字中分割出每個字符。那麼是怎麼做到的呢?
很簡單,我們看表的右邊,每一個 Unicode 編碼範圍對應的二進制數據的開頭,要麼是 0,要麼是一堆 1 加一個 0。計算機仍按照字節讀取,每個字節的開頭有幾個 1,這個字符就占幾個字節。
正是可變長度編碼的出現,才將 Unicode 的最大弱點 — 占用空間大的問題消滅,使得 Unicode 得以在全世界範圍內流行,成為計算機界的 “理想編碼”。
圖片、視頻和音頻的編碼#
圖片編碼#
圖片的編碼方式主要有兩種:無損編碼和有損編碼。無損編碼方式可以保留圖片的全部信息,但文件通常較大,常用的無損編碼方式有 GIF 和 PNG。有損編碼方式則通過犧牲部分信息來達到壓縮文件大小的目的,常用的有損編碼方式有 JPEG。
在計算機中,圖片以像素陣列的形式存儲。每個像素都是由紅、綠、藍三個顏色通道的亮度值組成的。在 GIF 和 PNG 這兩種無損編碼方式中,採用的是基於像素的編碼方式,即每個像素的值都單獨進行編碼。而在 JPEG 這種有損編碼方式中,採用的是基於變換的編碼方式,即將像素轉換為頻域上的變換系數進行編碼。
視頻編碼#
視頻編碼方式通常也採用有損編碼方式,以便壓縮視頻文件的大小。常用的視頻編碼標準有 MPEG-1、MPEG-2、MPEG-4、H.264、H.265 等。其中,MPEG-2 是用於 DVD 的標準,MPEG-4 則廣泛應用於各種流媒體應用。
視頻編碼的過程主要包括兩個步驟:空間預測和變換編碼。在空間預測中,每一幀的像素值都是由其前一幀像素值進行預測得到的。這樣可以大大減少每一幀需要編碼的信息量。而在變換編碼中,則採用了和 JPEG 類似的基於變換的編碼方式,將每一幀的像素值轉換為頻域上的變換系數進行編碼。
音頻編碼#
音頻編碼方式通常也採用有損編碼方式,以便壓縮音頻文件的大小。常用的音頻編碼標準有 MP3、AAC、WMA 等。其中,MP3 是最為流行的音頻編碼格式之一,它的壓縮率可以達到 10:1 或者更高。
音頻編碼的過程主要包括兩個步驟:時頻變換和熵編碼。在時頻變換中,將音頻信號轉換到時域和頻域上,以便更好地壓縮信號。而在熵編碼中,則根據信號的統計特徵,採用更有效率的編碼方式對信號進行編碼。
拓展閱讀#
其它進制的計算機#
其實,在計算機被發明的初期,也有十進制、三進制的計算機。
比如世界上第一台通用計算機 ENIAC 就是十進制。
而前蘇聯還曾造過一台三進制計算機Сетунь,它在不同的室溫下都表現出驚人的可靠性和穩定性,生產和維護也比同期其它計算機要容易得多。但後來…… 蘇聯官僚對這個經濟計劃外的科幻產物持否定的態度且勒令其停產。而此時,對Сетунь的訂單卻如雪片般從各方飛來,但 30 到 50 台的年產量遠不足以應付市場需求。
很快,計劃合作生產Сетунь的工廠倒閉了。1965 年,Сетунь停產了。取而代之的是一種二進制計算機,但價格卻貴出 2.5 倍。
最終,這個很有潛力的計算機被扼殺了……
為什麼用三進制#
其實,理論上 e 進制是存儲效率最高的進制,但是 e 畢竟是一個無理數,不太好實現,而 3 最接近 e,因此用了三進制。
至於數學上的證明…… 略有些複雜,你若感興趣可以看下一節。
我們只需要知道,三進制能用最少的存儲空間保存更多的數據。
進制效率的詳解#
本節中,對於 m 進制數 x,我們表示為 x (m)
我們先舉一個例子。
假設我們要用 2、3、5、10、16 進制表示十進制 0-9999 的 10000 個數字,每個數制需要多少數位?
因為 10011100001111 (2)=9999 (10)
所以2進制需要14個數位。
因為 111201100 (3)=9999 (10)
所以3進制需要9個數位。
因為 304444 (5)=9999 (10)
所以5進制需要6個數位。
因為 9999 (10)=9999 (10)
所以10進制需要4個數位。
因為 270F (16)=9999 (10)
所以16進制需要4個數位。
假設,現在要用卡片來表示這些數,每個數制各需要多少卡片?
如:5 進制中有 0,1,2,3,4 五個數字,那麼為了表示 1 位五進制數,我們需要準備 5 個卡片,也就是 1 位 n 進制數需要 n 個卡片
我們進行簡單的乘法即可得知:
2 進制需要個卡片
3 進制需要個卡片
5 進制需要個卡片
10 進制需要個卡片
16 進制需要個卡片
當然,這個過程中出現了「資源浪費」,也就是部分卡片實際可以表達的數比我們規定的上限 9999 (10) 多。
那麼,為了準確計算 x 進制表示 n 個數時需要用到多少卡片,我們需要用它表示 n 個數時的「理論位數」,乘以單個數位需要用的卡片數量 x。
什麼是「理論位數」?之前的例子中,我們說 3 進制表達 9999 (10) 需要 9 個數位,這是因為,向上取整得到 9;而 5 進制要 6 個數位是因為,向上取整得到 6。而這個向上取整的過程,就是之前提到的「資源浪費」。而 5.7726、8.3835(近似值)則是我們所說的「理論位數」。