原碼 補數 補碼以及計算機中為什麼用補碼儲存

2021-07-05 06:38:20 字數 3342 閱讀 5453

原碼:最左側一位表示符號,且0表示正數,1表示負數;二進位制轉換為十進位制時,符號位只用於取正負號,不參與轉化。

例如1個位元組的二進位制:

0000 0001表示十進位制的1;

0000 1010表示十進位制的10;

1000 0001表示十進位制的-1;

1000 1010表示十進位制的-10;

根據原碼的定義規則可知對於1個位元組的有符號二進位制原碼的取值範圍:[11111111]~[01111111]。即[-127]~[127]。比較特殊的是[10000000]表示-0,[00000000]表示+0,但是+0和-0是沒有意義的,後面講到補碼時會說到如何解決+0和-0的問題。這樣,對於1個位元組的有符號二進位制就可以表示256(2的8次方)個數值,包括+0和-0。

由以上可以看出,原碼表示法簡單直觀,但是對於計算機來說,要使計算機能夠自動識別最左側的符號位,就需要更為複雜的硬體設計;

另外,在原碼做減法運算時,根據數學上的加減乘除規則無法算出正確的值:

例如:1-1=1+(-1)=[00000001]原+[10000001]原=[10000010]原=-2

發現1-1不等於0。

總之,用原碼作為計算機的儲存方式不合適。

由上面可知,計算機不適合儲存原碼的原因是:1,無法識別二進位制左側的符號位;2,做減法時無法獲取正確的結果。那麼,有沒有一種方式可以既不用考慮二進位制左側的符號位,又能夠不做減法呢?

先來看乙個時鐘的例子,不考慮分和秒,生活中的鐘錶共1-12這12個刻度,假如此時時針指向6點鐘方向,要想讓它指向2點鐘方向則有兩種方式:1,逆時針移動4個刻度記作-4;2,順時針移動8個刻度記作+8。可發現,-4的絕對值加8等於12。則我們稱-4和8對於mod12互為補數。同樣-3和9對於mod12互為補數。也就是說我們可以找到乙個正數(8)代替負數(-4)用加法代替減法,且結果不變,如下圖。

模擬時鐘的邏輯,對於1個位元組的二進位制,共有256(2的8次方)種排列方式也就是可以表示256個數(類似於時鐘的12個數),則其mod為256。

補碼:正數的補碼是其本身;負數的補碼是符號位不變,其餘各位取反後再加1,也就是反碼加1。

例如:十進位制數1的原碼是0000 0001,其補碼也是0000 0001,不把左側第一位當成符號位直接轉換成十進位制仍是1。

十進位制數10的原碼是0000 1010,其補碼也是0000 1010,不把左側第一位當成符號位直接轉換成十進位制仍是10。

十進位制-1的原碼是1000 0001,則其補碼是1111 1111,不把左側第一位當成符號位直接轉換成十進位制是255,發現|-1|+255=256,說明-1的補碼就是其補數。

十進位制-10的原碼是1000 1010,則其補碼是1111 0110,不把左側第一位當成符號位直接轉換成十進位制是246,發現|-10|+246=256,說明-10的補碼就是其補數。

通過上面的例子,你會發現:1,補碼不用考慮符號位;2,補碼用加法代替了減法。這就很好的解決了原碼的兩個缺點。

為什麼負數的補碼是符號位不變,其餘各位取反再加1呢?

看看下面-10轉換為補碼的流程:

1 0 0 0 1 0 1 0   -10

1 1 1 1 0 1 0 1   取反

+                        1   加1

由上可知,取反後原來是0的位變成了1,則彌補了原來的位權(eg:對於1000,1的位權是1*2的3次方,左側第乙個0的位權是0*2的2次方)為0的問題;原來是1的位變成了0其位權也變為0;符號位也不再表示符號位而是1*2的7次方,因此取反會轉換為十進位制為245,再加1變為246,246+|-10|=256。因此負數的補碼是符號位不變,其餘各位取反再加1。

有了以上的了解,對於1個位元組的記憶體空間我們可以把資料在其中儲存的情況想象成乙個鐘錶的表盤:

對於上面的:

1:1個位元組的記憶體空間其0和1的組合方式有256(2的8次方)種。

2:內圈的數值(無符號)是計算機中實際儲存的補碼對應的十進位制。即不把符號位當成符號位而是當成普通的二進位制位後的十進位制數。其取值範圍是0~255,共256個數,可以理解成    鐘錶的256個刻度,即mod為256,內圈(補碼)的運算無符號無減法。

3:外圈的數值(有符號)是考慮符號位後補碼對應的原碼的十進位制值,也是我們實際需要的值。其取值範圍是-128~127,共256個數(很多人不理解為什麼範圍不是-127~127後面會解    釋)。

4:已經知道原碼的取值範圍是[-127]~[127],包括+0(00000000)和-0(10000000);

因為1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[0000 0001]補+[1111 1111]補=[1 0000 0000]補=[0000 0000]補=[0000 0000]原=+0,其中[1 0000 0000]補中的最高位1因為      溢位而被自動捨棄成[0000 0000]補。所以對於1個位元組的記憶體我們可以用[0000 0000]補表示0(+0)。

又因為-128=-1-127=(-1)+(-127)=[1000 0001]原+[1111 1111]原=[1111 1111]補+[1000 0001]補=[1 1000 0000]補=[1000 0000]補,其中[1 1000 0000]補的最高1溢位而自動舍     棄成[1000 0000]補,因此對於1個位元組的記憶體可以用[1000 0000]補來表示-128,需要說明的是[1000 0000]補只是拿出了原碼中的-0的二進位制形式用來表示-128的補碼形式,因   此並沒有原碼和反碼,檢視通過[1000 0000]補獲取其原碼或反碼的做法是錯誤的。

所以外圈取值範圍是-128~127,而不是-127~127。

5:計算機中儲存的是內圈的值(無符號無減法),而表現出來的卻是對應的外圈的值,即,計算機中儲存的是數的補碼,每乙個補碼對應乙個原碼。

總結:採用補碼儲存的方式,計算機不需要考慮符號,也不需要做減法。

下面舉1個例子驗證一下上圖是不是正確:

eg1:驗證-127逆時針移動2為指向127。

因為-127的補數是129(10000001),-2的補數是254(11111110)

所以-127-2=(-127)+(-2)=[1111 1111]原+[1000 0010]原=[1000 0001]補+[1111 1110]補=[1 0111 1111]補=[0111 1111]補=[0111 1111]原=127。

另外:根據資料在記憶體中是以補碼的形式存放的原理,可以很好理解,低位元組向高位元組擴充套件時,是帶符號擴充套件的。

例如:兩個位元組的有符號數,擴充套件為4個位元組時,若為負,則左側所有位元組全補1;若為正,則左側所有位元組全補0.

兩個位元組的無符號數擴充套件為4個位元組時,則左側全補0.

計算機中原碼 反碼 補碼

首先要明白,在計算機中,數以二進位制的形式存在,其中有無符號數和有符號數 無符號數的,相當於十進位制中的自然數,沒有負數,因此八位無符號數的範圍 00000000 11111111,而有符號數的最高位表示符號,最高位為0表示整數 0000 0001 1 最高位為1表示負數 1000 0001 1 原...

為什麼計算機中使用補碼?

週六加班的時候,乙個同事看到我在筆畫二進位制,就問我,這是啥,我跟他bb一大堆,然後他問我一句 為什麼計算機使用補碼,而不使用普通的 原碼 呢?這的確是乙個好問題。討論上述的內容之前,先預設大家都知道如下兩個知識 那麼在補碼沒有出現之前,我們怎麼使用原碼去快速的加減數?我們知道,如果乙個數a要減去乙...

計算機中的原碼 反碼和補碼

計算機中的原碼 反碼和補碼 看到這個標題,很多人有話要說了,切!這個東西每一本計算機基礎知識的書中都有介紹的,你還拿出來show什麼嘛!我的原則是你需要就來看一看,懂就不要去理會,倒也不必諷刺兩句,我相信總有需要它的人。當初我看書是沒看明白的,在網上查了好多資料才有所悟。前幾天跟老婆講原碼 反碼和補...