天天看點

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

我們知道,計算機隻認識0和1[為什麼計算機隻認識0和1],現實世界中的内容,無論是文字、音頻、視訊等等想要通過計算機存儲、計算或者展示,都需要轉換二進制。

就像你剛剛唱的旋律,想要存儲在計算機中也是要轉成二進制的。

那麼,最簡單的一個數字,想要在計算機中表示出來,就需要通過一定的手段将他轉換成二進制。而這種手段我們稱之為編碼方式。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

原碼

相信很多人在上國中的時候都學過很多方式把一個十進制數轉成二進制數,比如我們可以很快速的知道10的二進制可以表示成 1010 。

但是國中老師沒有告訴我們的是:-10 如何表示呢?

為了在計算機中想辦法表示負數。于是人們想出來一種辦法:

在二進制數值前面增加一位符号位(即最高位為符号位):正數該位為0,負數該位為1,其餘位表示數值的大小。

這樣,如果我們想要10的話,那麼就應該是:0 1010,想要表示-10的話,就應該是1 1010。

這種編碼方式被稱之為原碼,原碼的優點比較明顯,那就是非常的簡單直覺,很容易被人了解。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

使用原碼,解決了十進制在計算機中的存儲問題,但是計算機中還有一個重要的操作那就是計算。使用原碼如何計算呢?

首先,原碼對于加法的運算是沒什麼問題的,如<code>5 + 2</code> :

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

對應的二進制運算:0 0101(原) + 0 0010(原) = 0 0111(原) 其對應的十進制是 7。

加法沒什麼問題,那麼我們再試着用原碼來計算減法,例如我們想要計算10 - 2:

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

那麼就是 0 1010(原) - 0 0010(原) = 0 1000(原),那麼這個二進制對應的十進制剛好是8。可見原碼計算減法沒有問題的?

但是,以上運算隻是我們一廂情願的算法,其實計算機算術邏輯單元(ALU)并沒有直接進行減法運算,對于減法,其實也是用加法器來實作的。

也就是說,計算機中的所有的減法運算都需要轉換成加法運算,那麼<code>10 - 2</code>其實就是<code>10 + (-2)</code>:

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

他們的二進制 0 1010(原) + 1 0010(原) = 1 1100(原) ,得到的結果考慮他的符号位的話,這個值是-12,這明顯是錯誤的!!!

可見,原碼雖然對于人類來說是比較簡單直覺的,但是對于計算機來說卻帶來了很大的計算難度。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

反碼

因為原碼雖然容易被人了解,但是給計算機的計算帶來了一定的困難,尤其是減法的運算。是以,人們發明出反碼來解決減法運算的問題。

反碼是基于原碼計算得來的,表示方式是:正數的反碼是其本身。負數的反碼是在其原碼的基礎上, 符号位不變,其餘各個位取反。

如,10 的 原碼為 0 1010 ,那麼他的反碼同樣也是 0 1010 。

如,-2 的原碼為 1 0010 ,那麼他的反碼為 1 1101 。

有了反碼之後,二進制的運算就可以帶着符号位一起了。并且可以直接将減法轉換成加法進行運算。但是使用反碼進行運算,需要注意以下幾點:

反碼運算時,其符号位與數值一起參加運算。

反碼的符号位相加後,如果有進位出現,則要把它送回到最低位去相加(循環進位)。

用反碼運算,其運算結果亦為反碼。在轉換為真值時,若符号位為0,數位不變;若符号位為1,應将結果求反才是其真值。

如 10 - 2 的在計算時需要轉成 10 + (-2)進行計算:

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

0 1010(反) + 1 1101(反) = 0 0111(反) + 1(進位) = 0 1000 ,因為符号位是0,表示正數,是以他對應的原碼也是0 1000(原),則十進制值為8。

那麼,我們再來計算法 2 - 10 ,把2 - 10轉換成 2 + (-10)進行計算:

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

0 0010(反) + 1 0101(反) = 1 0111(反),因為符号位是1,表示負數,是以他對應的原碼也是1 1000(原),則十進制為-8。

以上,我們通過幾個例子展示了反碼,我們知道使用反碼進行計算的時候,可以帶着符号位一起計算,隻需要在計算之後再将反碼轉換成原碼,再計算其對應的十進制就可以了。

但是,反碼運算還是有一個小問題,我們看一下下面這個例子:

我們嘗試計算10 - 10 ,即 10 + (-10):

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

0 1010(反) + 1 0101(反) = 1 1111(反),因為符号位是1,表示負數,是以他對應的原碼也是1 0000(原),則十進制為-0。

雖然很多人夠能夠了解+0和-0其實是一樣的,但是0帶符号仍然是沒有任何意義的。

如果一台計算機有8位,我們想要用反碼表示0的話,就有0000 0000和 1111 1111兩種方式,分别表示+0和-0。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

補碼

雖然反碼解決了減法的問題,但是對于0的符号問題卻沒有解決,于是補碼出現了。

補碼是在原碼和反碼的基礎上衍生出來的,補碼的表示方法是:正數的補碼就是其本身,負數的補碼是在其原碼的基礎上, 符号位不變, 其餘各位取反,最後+1。(即在反碼的基礎上+1)

補碼計算的規則:

補碼運算時,其符号位與數值一起參加運算。

補碼的符号位相加後,如果有進位出現,則進位被舍棄。

用反碼運算,其運算結果亦為補碼。在轉換成原碼時,如果是正數,其補碼就是原碼;如果是負數,該補碼的補碼就是其原碼。

我們再來用補碼的方式,來計算下10 - 10 :

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

01010(補) + 10110(補) = 0 0000 (補),因為符号位是0,表示正數,是以他對應的原碼也是0 0000(原),則十進制為0。

有了補碼,0的表達方式就唯一了,如果是8位的話,那麼就是固定的0000 0000。

如果使用原碼或者反碼,8位的原碼或者反碼能表示的最小數字是-127,而使用補碼,能表示的最小數字是-128。

可見,使用補碼, 不僅僅修複了0的符号以及存在兩個編碼的問題, 而且還能夠多表示一個最低數。這就是為什麼8位二進制, 使用原碼或反碼表示的範圍為[-127, +127], 而使用補碼表示的範圍為[-128, 127]。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

使用補碼的原因

通過以上介紹,我們知道了原碼、反碼和補碼的一些知識,我們嘗試着總結下為什麼計算機中會最終選擇補碼來進行存儲和計算數字。

1、計算機的運算器為了實作簡單,傾向于在運算過程中将減法轉換成加法,統一使用加法運算器進行計算。想要把減法轉化成加法運算,就需要在運算時帶着符号一起運算,而反碼和補碼可以帶符号位一起運算,也就友善了将減法轉換為加法。

2、采用補碼,可以解決編碼中有+0和-0兩種表示0的方式。

3、補碼表示的數字範圍要比原碼和反碼大。如8位2進制,使用原碼或反碼表示的範圍為[-127, +127], 而使用補碼表示的範圍為[-128, 127]。

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!
醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!

關于作者:漫話程式設計,是一個通過漫畫+音頻的形式講解枯燥的程式設計知識的公衆号。緻力于讓程式設計變得更有樂趣。

有道無術,術可成;有術無道,止于術

醉了!吃着火鍋哼着歌,男朋友強行給我科普什麼是補碼!