【轉載】二進制編碼

本文轉載,原文連接不詳程序員

 

負數:學習

原碼就是原來的表示方法編碼

反碼是除符號位(最高位)外取反spa

補碼=反碼+1設計

之前學習二進制編碼時,老師講了一堆堆的什麼原碼啊反碼啊補碼啊xxxx轉換啊,還有負數的表示方式啊 老是記不零清,終於從網上找到了一種比較好的講解方式,保存再share一下,不過爲了系統化講解,又找來了一些編碼的基礎知識,若是隻想看負數編碼記憶法,請跳轉到blog

1.若是你不知道二進制怎麼編碼,請繼續,不然請跳到2get

    1字節 = 8位,因此它能表示的最大數固然是8位都是1(既然2進制的數只能是0或1,若是是咱們常見的10進制,那就8位都爲9,這樣說,你該懂了?)數學

1字節的二進制數中,最大的數:11111111。it

    這個數的大小是多少呢?讓咱們來把它轉換爲十進制數。io

    不管是什麼進制,都是左邊是高位,右邊是低位。10進制是咱們很是習慣的計數方式,第一位表明有幾個1(即幾個100),第二位表明有幾個10(即幾個101),第三位表明有幾個100(即有幾個102)…,用小學課本上的說法就是:個位上的數表示幾個1,十位上的數表示向個10,百位上的數表示幾個100……

    同理可證,二進制數則是:第1位數表示幾個1 (20),第2位數表示幾個2(21),第3位數表示幾個4(22),第4位數表示向個8(23)……

    之前咱們知道1個字節有8位,如今經過計算,咱們又得知:1個字節能夠表達的最大的數是255,也就是說表示0~255這256個數。

     那麼兩個字節(雙字節數)呢?雙字節共16位。 1111111111111111,這個數並不大,但長得有點眼暈,從如今起,咱們要學會這樣來表達二制數:

1111 1111 1111 1111,即每4位隔一空格。

雙字節數最大值爲:

1 * 215 + 1 *214 + 1* 213 + 1 * 212 + 1 * 211 + 1 * 210 + …… + 1 * 22 + 1 * 21 + 1* 20 = 65535

    很天然,咱們能夠想到,一種數據類型容許的最大值,和它的位數有關。具體的計算方法方法是,若是它有n位,那麼最大值就是:

n位二進制數的最大值:1 * 2(n-1) + 1 * 2(n-2) + ... + 1 * 20

二、理解有符號數和無符號數

負數在計算機中如何表示呢?這一點,你可能聽過兩種不一樣的回答。

一種是教科書,它會告訴你:計算機用「補碼」表示負數。但是有關「補碼」的概念一說就得一節課,這一些咱們須要在第6章中用一章的篇幅講2進制的一切。再者,用「補碼」表示負數,其實一種公式,公式的做用在於告訴你,想得問題的答案,應該如何計算。卻並無告訴你爲何用這個公式就能夠和答案? -----我就是被這個弄混淆的>_<

另外一種是一些程序員告訴你的:用二進制數的最高位表示符號,最高位是0,表示正數,最高位是1,表示負數。這種說法自己沒錯,但是若是沒有下文,那麼它就是錯的。至少它不能解釋,爲何字符類型的-1用二進制表示是「1111 1111」(16進製爲FF);而不是咱們更能理解的「1000 0001」。(爲何說後者更好理解呢?由於既然說最高位是1時表示負數,那1000 0001不是正好是-1嗎?-----re!當初偶就是這麼想的,so一直在腦中打架,越打越混淆=,=)。

讓咱們從頭提及。

2.一、你自已決定是否須要有正負。

就像咱們必須決定某個量使用整數仍是實數,使用多大的範圍數同樣,咱們必須自已決定某個量是否須要正負。若是這個量不會有負值,那麼咱們能夠定它爲帶正負的類型。

在計算機中,能夠區分正負的類型,稱爲有符類型,無正負的類型(只有正值),稱爲無符類型。

數值類型分爲整型或實型,其中整型又分爲無符類型或有符類型,而實型則只有符類型。

字符類型也分爲有符和無符類型。

好比有兩個量,年齡和庫存,咱們能夠定前者爲無符的字符類型,後者定爲有符的整數類型。

二、使用二制數中的最高位表示正負。

首先得知道最高位是哪一位?1個字節的類型,如字符類型,最高位是第7位,2個字節的數,最高位是第15位,4個字節的數,最高位是第31位。不一樣長度的數值類型,其最高位也就不一樣,但老是最左邊的那位(以下示意)。字符類型固定是1個字節,因此最高位老是第7位。

(紅色爲最高位)

單字節數: 1111 1111

雙字節數: 1111 1111 1111 1111

四字節數: 1111 1111 1111 1111 1111 1111 1111 1111

當咱們指定一個數量是無符號類型時,那麼其最高位的1或0,和其它位同樣,用來表示該數的大小。

當咱們指定一個數量是有符號類型時,此時,最高數稱爲「符號位」。爲1時,表示該數爲負值,爲0時表示爲正值。

 三、無符號數和有符號數的範圍區別。

無符號數中,全部的位都用於直接表示該值的大小。有符號數中最高位用於表示正負,因此,當爲正值時,該數的最大值就會變小。咱們舉一個字節的數值對比:

無符號數: 1111 1111   值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

有符號數: 0111 1111   值:127         1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

  一樣是一個字節,無符號數的最大值是255,而有符號數的最大值是127。緣由是有符號數中的最高位被挪去表示符號了。而且,咱們知道,最高位的權值也是最高的(對於1字節數來講是2的7次方=128),因此僅僅少於一位,最大值一會兒減半。

不過,有符號數的長處是它能夠表示負數。所以,雖然它的在最大值縮水了,卻在負值的方向出現了伸展。咱們仍一個字節的數值對比:

無符號數:                       0 ----------------- 255

有符號數:        -128 --------- 0 ---------- 127

 

一樣是一個字節,無符號的最小值是 0 ,而有符號數的最小值是-128。因此兩者能表達的不一樣的數值的個數都同樣是256個。只不過前者表達的是0到255這256個數,後者表達的是-128到+127這256個數。

一個有符號的數據類型的最小值是如何計算出來的呢?

有符號的數據類型的最大值的計算方法徹底和無符號同樣,只不過它少了一個最高位(見第3點)。但在負值範圍內,數值的計算方法不能直接使用1* 26 + 1* 25 的公式進行轉換。在計算機中,負數除爲最高位爲1之外,還採用補碼形式進行表達。因此在計算其值前,須要對補碼進行還原。這裏,先直觀地看一眼補碼的形式:

以咱們原有的數學經驗,在10進制中:1 表示正1,而加上負號:-1 表示和1相對的負值。

那麼,咱們會很容易認爲在2進制中(1個字節): 0000 0001 表示正1,則高位爲1後:1000 0001應該表示-1。

然而,事實上計算機中的規定有些相反,請看下錶:

 

 

二進制值(1字節) 十進制值
1000 0000紅色的1表明負數藍色的是補碼(補碼=反碼+1) -128
1000 0001藍色部分表明多大的值?:將補碼還原爲原碼 -127想化成負數?:先減去1按位取反
1000 0010還原方法:補碼-1再取反 -126
1000 0011 -125
... ...
1111 1110 -2
1111 1111 -1

 

 

首先咱們看到,從-1到-128,其二進制的最高位都是1(表中標爲紅色),正如咱們前面的學。

而後咱們有些奇怪地發現,1000 0000 並無拿來表示 -0;而1000 0001也不是拿來直觀地表示-1。事實上,-1 用1111 1111來表示。

怎麼理解這個問題呢?先得問一句是-1大仍是-128大

固然是 -1 大。-1是最大的負整數。以此對應,計算機中不管是字符類型,或者是整數類型,也不管這個整數是幾個字節。它都用全1來表示 -1。好比一個字節的數值中:1111 1111表示-1,那麼,1111 1111 - 1 是什麼呢?和現實中的計算結果徹底一致。1111 1111 - 1 = 1111 1110,而1111 1110就是-2。這樣一直減下去,當減到只剩最高位用於表示符號的1之外,其它低位全爲0時,就是最小的負值了,在一字節中,最小的負值是1000 0000,也就是-128。

--------小米批註:就是這部分藍色的文字,讓我終於能記清楚-1的編碼方式了,汗=。=

咱們以-1爲例,來看看不一樣字節數的整數中,如何表達-1這個數:

 

字節數 二進制值 十進制值
單字節數 1111 1111紅色表示負數藍色部分的補碼爲值1 -1
負數:原碼就是原來的表示方法、反碼是除符號位(最高位)外取反、補碼=反碼+1雙字節數 1111 1111 1111 1111 -1
四字節數 1111 1111 1111 1111 1111 1111 1111 1111 -1

 

可能有同窗這時會混了:爲何 1111 1111 有時表示255,有時又表示-1?因此我再強調一下本節前面所說的第2點:你自已決定一個數是有符號仍是無符號的。寫程序時,指定一個量是有符號的,那麼當這個量的二進制各位上都是1時,它表示的數就是-1;相反,若是事選聲明這個量是無符號的,此時它表示的就是該量容許的最大值,對於一個字節的數來講,最大值就是255。

ok 摘抄暫告段落,其實原文對於c的一些基礎數據類型知識介紹的很是詳細,8過太長了,摘到我須要的內容後就沒全帖過來,若是有須要學習的同窗,建議參見原文:)

轉自http://blog.cersp.com/7892477/1201309.aspx

關鍵字: 二進制編碼,負數二進制,二進制

 
2007-09-09 14:24:25
   
標籤: 教育雜談

    在計算機內部,全部信息都是用二進制數串的形式表示的。整數一般都有正負之分,計算機中的整數分爲無符號的和帶符號的。無符號的整數用來表示0和正整數,帶符號的證書能夠表示全部的整數。因爲計算機中符號和數字同樣,都必須用二進制數串來表示,所以,正負號也必須用0、1來表示。一般咱們用最高的有效位來表示數的符號(當用8位來表示一個整數時,第8位即爲最高有效位,當用16位來表示一個整數時,第16位即爲最高有效位。)0表示正號、1表示負號,這種正負號數字化的機內表示形式就稱爲「機器數」,而相應的機器外部用正負號表示的數稱爲「真值」。將一個真值表示成二進制字串的機器數的過程就稱爲編碼。

    無符號數沒有原碼、反碼和補碼一說。只有帶符號數才存在不一樣的編碼方式。

帶符號整數有原碼、反碼、補碼等幾種編碼方式。原碼即直接將真值轉換爲其相應的二進制形式,而反碼和補碼是對原碼進行某種轉換編碼方式。正整數的原碼、反碼和補碼都同樣,負數的反碼是對原碼的除符號位外的其餘位進行取反後的結果(取反即若是該位爲0則變爲1,而該位爲1則變爲0的操做)。而補碼是先求原碼的反碼,而後在反碼的末尾位加1 後獲得的結果,即補碼是反碼+1。IBM-PC中帶符號整數都採用補碼形式表示。(注意,只是帶符號的整數採用補碼存儲表示的,浮點數另有其存儲方式。)

    採用補碼的緣由或好處以下。

    採用補碼運算具備以下兩個特徵:

    1)由於使用補碼能夠將符號位和其餘位統一處理,同時,減法也能夠按加法來處理,即若是是補碼錶示的數,無論是加減法都直接用加法運算便可實現。

    2)兩個用補碼錶示的數相加時,若是最高位(符號位)有進位,則進位被捨棄。

    這樣的運算有兩個好處:

    1)使符號位能與有效值部分一塊兒參加運算,從而簡化運算規則。從而能夠簡化運算器的結構,提升運算速度;(減法運算能夠用加法運算表示出來。)

    2)加法運算比減法運算更易於實現。使減法運算轉換爲加法運算,進一步簡化計算機中運算器的線路設計。

    下面深刻分析上面所陳述的採用補碼的緣由(目的)。

    用帶符號位的原碼進行乘除運算時結果正確,而在加減運算的時候就出現了問題,以下:假設字長爲8bits

    ( 1 ) 10- ( 1 )10 = ( 1 )10 + ( -1 )10 = ( 0 )10

    (00000001)原 + (10000001)原 = (10000010)原 = ( -2 ) 顯然不正確.。

    由於在兩個整數的加法運算中是沒有問題的,因而就發現問題出如今帶符號位的負數身上,對除符號位外的其他各位逐位取反就產生了反碼。反碼的取值空間和原碼相同且一一對應。下面是反碼的減法運算:

     ( 1 )10 - ( 1 ) 10= ( 1 ) 10+ ( -1 ) 10= ( 0 )10

     (00000001) 反+ (11111110)反 = (11111111)反 = ( -0 ) 有問題。

    ( 1 )10 - ( 2)10 = ( 1 )10 + ( -2 )10 = ( -1 )10

     (00000001) 反+ (11111101)反 = (11111110)反 = ( -1 ) 正確

    問題出如今(+0)和(-0)上,在人們的計算概念中零是沒有正負之分的。

因而就引入了補碼概念。負數的補碼就是對反碼加一,而正數不變,正數的原碼反碼補碼是同樣的。在補碼中用(-128)代替了(-0),因此補碼的表示範圍爲:

(-128~0~127)共256個。

    注意:(-128)沒有相對應的原碼和反碼, (-128) = (10000000) 補碼的加減運算以下:

    ( 1 ) 10- ( 1 ) 10= ( 1 )10 + ( -1 )10 = ( 0 )10

    (00000001)補 + (11111111)補 = (00000000)補 = ( 0 ) 正確

     ( 1 ) 10- ( 2) 10= ( 1 )10 + ( -2 )10 = ( -1 )10

    (00000001) 補+ (11111110) 補= (11111111)補 = ( -1 ) 正確

    採用補碼錶示還有另一個緣由,那就是爲了防止0的機器數有兩個編碼。原碼和反碼錶示的0有兩種形式+0和-0,而咱們知道,+0和-0是相同的。這樣,8位的原碼和反碼錶示的整數的範圍就是-127~+127(11111111~01111111),而採用補碼錶示的時候,00000000是+0,即0;10000000再也不是-0,而是-128,這樣,補碼錶示的數的範圍就是-128~+127了,不但增長了一個數得表示範圍,並且還保證了0編碼的惟一性。

    整數和0的原碼、反碼和補碼都相同,下面介紹手工快速求負數補碼的方法。這個方法在教材的第8頁已經提到了,這裏再寫出來以便能引發你們的注意。其方法以下:

    先寫出該負數的相反數(正數),再將該正數的二進制形式寫出來,而後對這個二進制位串按位取反,即如果1則改成0,如果0則改成1,最後在末位加1。

接下來的問題是,如何能將減法運算轉換成加法運算呢?

    咱們已經知道,原碼錶示簡單直觀,與真值轉換容易。但若是用原碼錶示,其符號位不能參加運算。在計算機中用原碼實現算術運算時,要取絕對值參加運算,符號位單獨處理,這對乘除運算是很容易實現的,但對加減運算是很是不方便的,如兩個異號數相加,實際是要作減法,而兩個異號數相減,實際是要作加法。在作減法時,還要判斷操做數絕對值的大小,這些都會使運算器的設計變得很複雜。而補碼這種編碼方式實際上正是針對上述問題的。經過用補碼進行表示,就能夠把減法運算化爲加法運算。

    在平常生活中,有許多化減爲加的例子。例如,時鐘是逢12進位,12點也可看做0點。當將時針從10點調整到5點時有如下兩種方法:

    一種方法是時針逆時針方向撥5格,至關於作減法:

        10-5=5

    另外一種方法是時針順時針方向撥7格,至關於作加法:

      10+7=12+5=5    (MOD 12)

    這是因爲時鐘以12 爲模,在這個前提下,當和超過12時,可將12捨去。因而,減5至關於加7。同理,減4可表示成加8,減3可表示成加9,…。

    在數學中,用「同餘」概念描述上述關係,即兩整數AB用同一個正整數M (M稱爲模)去除而餘數相等,則稱A、BM同餘,記做:

       AB     (MOD M)

    具備同餘關係的兩個數爲互補關係,其中一個稱爲另外一個的補碼。當M=12時,-5和+7,-4和+8,-3和+9就是同餘的,它們互爲補碼。

    從同餘的概念和上述時鐘的例子,不可貴出結論:對於某一肯定的模,用某數減去小於模的另外一個數,總能夠用加上「模減去該數絕對值的差」來代替。所以,在有模運算中,減法就能夠化做加法來作。

    能夠看出,補碼的加法運算所依據的基本關係爲:

[x]補+ [y]補= [x+y]補

    補碼減法所依據的基本關係式:

[x-y]補 =[x+(-y)]補= [x]補+ [-y]補

    至於加法運算爲何比減法運算易於實現以及CPU如何實現各類算術運算等問題,則須要經過對數字電路的學習來理解CPU的運算器的硬件實現問題的相關內容了。

相關文章
相關標籤/搜索