關於定點數 原碼 反碼 補碼的理解

2021-09-10 12:25:17 字數 3884 閱讀 2555

原碼的存在是最自然而然的。把人類書寫的數按轉換成二進位制,正常情況下,轉換成的二進位制有位數要求,比如,轉換成8位的,等等。但是如果給出的數是5,轉換成二進位制是三位,101,這個時候要在左面補0,補齊八位,成為0000 0101。但是,這個時候的二進位制數並不是我們所要的原碼,還缺了最後一步:符號。如果是正數,最左面的位,也就是最高位要置0,反之,是負數就將其置1。這樣5的表示是0000 0101,而-5的表示是 1000 0101。

這樣,在讀的時候,機器預設8位的最高位是符號位,表示數的正負,而剩餘的7位由二進位制轉換為十進位制,即可得到我們慣用的表示。

所以顯而易見,如果給出的數是255,他的二進位制數是1111 1111,按照我們上面的邏輯,它是正數,應該把最高位置0,但是,0111 1111,機器將會讀成127;與我們最初的數並不相同,即資料出錯。所以啊,8位能表示的數的範圍就是-127到127的整數,如果不在範圍內,卻轉換成8位來存,讀錯也是沒有辦法的事情。

事實上,計算機所能存的數受機器字位數的限制,超出以後就發生溢位,將不能保證資料的正確性。除此之外,由於計算機設計的原因,機器字所能表示的範圍,不止受機器字位數的限制,也受設計過程中預設的約定的影響,一些特殊的值對應的碼可能會被賦予其他含義。

原碼表示中有乙個特殊的數,0。0有兩種表示,+0和-0。其原碼分別為1000 0000,和0000 0000。但是,這是原碼的乙個痛點(然而並不是最大的痛點,最大的痛點是原碼,沒有減法)。

我所能想到的我們為什麼要有反碼的原因,就是減法了。

雖然最後證明是補碼拯救了定點數的減法,但是我想反碼作為乙個中間產品出現,雖然有不足,但也解決了原碼的某些問題。

首先丟擲結論,反碼可以解決減法問題,但是有兩點瑕疵:

互為相反數的兩個數,其反碼各位均異,導致其相加結果為-0(原碼中痛點的延續,此時成為了最大的痛點,這就是主要矛盾消失了,次要矛盾就會顯現出來),而-0與+0的同時存在使得同乙個數值對應不同的編碼,造成很多麻煩;

使用反碼計算減法,要使用迴圈進製,即最高位有溢位,則加1,否則,不加1。這一點使得在正數原碼加法的基礎上要求新的硬體結構。

接下來解釋一下反碼計算的本質,反碼計算如果沒有迴圈進製,就什麼也不是,而迴圈進製,並不是因為恰好每當這個時候加乙個1就是正確答案,它的根源在於計算的機器字位數有限,能表示的範圍有限。

接下來描述機器字有限的後果。例如八位,只能表示-127到+127,如果不把第一位當做符號位,其範圍也只是0到255。255再加1時,發生溢位,但是溢位只是因為沒有更高的位來存我們的進製,此時現有的八位為0000 0000,若不計溢位,即我們規定最高位沒有進製,則此時值為0;以此類推,256=0,257=1,...,511=255,512=0,...;永遠在0到255之間迴圈往復,這就是取模運算。

需要區分的是取模運算和取餘運算,兩者的計算原理都是一樣的,a/b=c......d,其中a、b、c、d都是整數,取餘或者取模運算的結果就是d。但是a/b=c......d的結果並不是唯一的,比如 4/8=0......4,或者4/8=1......-4,再比如-7/2=-3......-1,或者-7/2=-4......1。這其中的不同,導致了取餘和取模的區分。對於取餘運算來說,要求商盡可能趨近0,比如雖然4/8的商可以是0,也可以使1,但是因為我們要趨近0,所以對於取餘運算來說,取得的餘數就是4;在比如,-7/2的商可以是-3,也可以使-4,但是因為要趨近與0,所以商是-3,餘數是-1。取模運算並不是與取餘運算完全相反,因為它並不是要求盡量不趨近於0,而是要求盡量趨近於負無窮,所以,對於商在零點以及正半軸來說,跟取餘運算是一樣的,但是對於負半軸來說,恰好相反,比如,-7/2的商,因為要求趨近於負半軸,所以商是-4,餘數是1。事實上,取模運算的整數商要趨於負無窮,這一要求的本質是,要求餘數必須是大於等於0的數。也就是說,我們取模運算得到的結果一定是自然數。而自然數對於計算機來說是無符號整數,表示是最簡單的了。

所以取模運算是計算機乙個十分重要的運算,不僅是因為機器字的有限位決定了取模運算的常見性,更重要的是因為取模運算本身契合了計算機的位數有限,無符號整型的表示。 

反碼減法的本質是,將有符號整型的減法,轉換成無符號整型的加法,而無符號整型的加法是模運算。

(1)z=y-x      z'=y-x+256=y+[128+(127-x)]+1      z是我們想要的結果

如果z>=0,則z'%256=z,z'/256=1

如果z<0,則z'%256=256-|z|=128+(127-|z|)+1=z』,所以y+[128+(127- x)]=128+(127-|z|), z'/256=0

(2)z=-y-x      z'=256*2-y-x=[128+(127-x)]+[128+(127-y)]+2

z'%256=256-|z|=128+(127-|z|)+1,所以[128+(127-x)]+[128+(127-y)]+1=128+(127- |z|), z'/256=1

總結以上兩點,在參與運算時,負數全部化成128+(127-x)的形式,轉化後的兩數相加得到和,結果為和取模與和除以模的商相加,如果此時的結果大於128,那麼說明結果是負數,現在的形式是128+(127-z);反之,說明結果是正數,現在的形式即為結果。這就是反碼和迴圈進製的本來面目了。

說實話,從原碼到反碼,是一項十分精彩的進步,之後從反碼到補碼就沒有這個精彩了。

補碼和反碼的親緣關係很近。補碼之所以成為定點數減法的最終解決方案,在於他完美地解決了反碼中的兩個痛點。

補碼的定義:

從反碼的本質看補碼的產生:

(1)z=y-x      z'=y-x+256=y+[128+(127-x+1)]    z是我們想要的結果

如果z>=0,則z'%256=z

如果z<0,則z'%256=256-|z|=128+(127-|z|+1)=z',所以y+[128+(127- x+1)]=128+(127-|z|+1)

(2)z=-y-x      z'=256*2-y-x=[128+(127-x+1)]+[128+(127-y+1)]

z'%256=256-|z|=128+(127-|z|+1),所以[128+(127-x+1)]+[128+(127-y+1)]=128+(127-|z|+1)

而從無符號整型的角度看負數的補碼即為128+(127-x+1)

由上可知反碼的本質,也是補碼的本質,改變了形式,使得對於商的判斷融入了取模運算本身簡化了運算的邏輯。然而這一舉措的實質是,對於反碼來說,-x的反碼是(模-1-x),而-x的補碼是(模-x),從「模-1」到「模」的變化,是從反碼到補碼的變化的實質。舉個例子,y-x,反碼的計算,從無符號整型的角度看,本身是y+[128+(127-x)],即255+(y-x),當(y-x)大於0的時候,由於計算機的模運算,結果將會變為[255+(y-x)]%256=[256+(y-x-1)]%256=y-x-1,即,在存在進製的情況下,反碼計算的直接結果,由於為了進製滿足模,而從後面的式子裡拿走了乙個1,導致結果總是少1,所以迴圈進製需要加1。

而現在,在補碼的運算過程中,從無符號整型的角度看,本身是y+[128+(127-x+1)],即256+(y-x),當y-x是正數以及0的情況下,計算機的取模運算直接消除了式子中的256,得到正確結果。所以說,從反碼到補碼的變化實質,是從「模-1」到「模」的變化。

根據以上解釋,稍加思考,就能明白所謂的迴圈進製,本質是為了彌補進製從後面式子中拿走的1,所以在存在進製的情況下,要為得到的結果加1。而在補碼中,並不存在為了進製而從後面的式子裡拿1這個操作,所以,進製不進製並不造成影響。由此,消除了迴圈進製。

同時,由於補碼的形式,使得-0的補碼與+0的補碼相同,即都為0000 0000,消除了0的編碼不唯一的缺點(總算是克服了)。同時,由於八位的取值是從-127到127,所以補碼也是從256-127到256-0,以及從0到127,並起來,即為[0,127]並[129,256],其中128沒有任何乙個數的補碼是它。約定128是-128(這個本來不存在的數)的補碼。

注意:關於定點數的位數擴充套件,需要注意的是,位數擴充套件要向遠離小數點的方向擴充套件。擴充套件時,左邊擴充套件出的位,用符號位填充(純整數),右邊擴充套件出的位用0填充(純小數)

算術右移,左邊空出來的位置要用符號位補齊;算術左移,右邊空出來的位置補0即可。

定點數表示方法 原碼,補碼,反碼,移碼

1.真值和機器數 真值 數的實際值,用正負號和絕對值的某進製形式來表示,如 1010,12,ffff等.機器數 真值在計算機中的二進位制表示,特點是符號數位化且數的大小受機器字長限制,其表示形式有原碼,補碼,反碼,移碼等.2.原碼.1 定點小數 left x left x right 1 x le ...

關於原碼 補碼 反碼的理解

補下基礎 原碼 補碼 反碼 正數補碼 反碼都和原碼一樣,符號位為0 負數原碼 符號位為1,其他位為 絕對值表示的二進位制數 反碼 原碼符號位不變 其他位按位取反 補碼 反碼 1 反碼的問題是 00000000 為0,反碼為 00000000 10000000 也為0,反碼為 11111111 這樣0...

原碼 反碼 補碼的理解

1 討論原碼之前首先需要了解兩個概念 機器數和真值。a.乙個數值在計算機中的二進位制表示形式,就稱為這個數值的機器數。機器數是帶符號的,其中最高位是符號位,1表示負數,0表示正數。比如,1100 0000就是 64的機器數,即在計算機中的二進位制表示形式。同樣的,0100 0000就是64的機器數。...