計算機中的原碼,反碼,補碼,以及他們在記憶體中的儲存形式。
1.原碼
原碼就是早期用來表示數字的一種方式: 一個正數,轉換為二進位制位就是這個正數的原碼。負數的絕對值轉換成二進位制位然後在高位補1就是這個負數的原碼
舉例說明:
int型別的 3 的原碼是 11B(B表示二進位制位), 在32位機器上佔四個位元組,那麼高位補零就得:
00000000 00000000 00000000 00000011
int型別的 -3 的絕對值的二進位制位就是上面的 11B 展開後高位補零就得:
10000000 00000000 00000000 00000011
但是原碼有幾個缺點,
a.零分兩種 +0 和 -0 。
b.在進行不同符號的加法運算或者同符號的減法運算的時候,不能直接判斷出結果的正負。需要將兩個值的絕對值進行比較,然後進行加減操作,
最後符號位由絕對值大的決定。於是反碼就產生了。
2.反碼
正數的反碼就是原碼,負數的反碼等於原碼除符號位以外所有的位取反
舉例說明:
int型別的 3 的反碼是
00000000 00000000 00000000 00000011
int型別的 -3 的反碼是
11111111 11111111 11111111 11111100
除開符號位 所有位 取反
解決了加減運算的問題,但還是有正負零之分,然後就到補碼了
3.補碼
正數的補碼與原碼相同,負數的補碼為 其原碼除符號位外所有位取反(得到反碼了),然後最低位加1.
還是舉例說明:
int型別的 3 的補碼是:
00000000 00000000 00000000 00000011
int型別的 -3 的補碼是
11111111 11111111 1111111 11111101
就是其反碼加1
總結:
a.正數的反碼和補碼都與原碼相同。
b.負數的反碼為對該數的原碼除符號位外各位取反。
c.負數的補碼為對該數的原碼除符號位外各位取反,然後在最後一位加1
d.原碼好理解了,但是加減法不夠方便,還有兩個零(正負0)
e.反碼稍微困難一些,解決了加減法的問題,但還是有兩個零
f.補碼理解困難
4.數在記憶體中都是以補碼形式存在的
對於一個負數-x,它的二進位制表示(補碼)求法如下:
a.對x的原碼進行取反運算
b.將取反運算的結果+1
對於大多數語言來說,char型別的有效範圍是-128~127,那麼如果我們把128這個超過了char型別表示範圍的數賦值給一個char型變數ch,結果會怎樣呢?ch的值會變成0,還是其它值?答案是,ch的值會變成-128,因為128超越了最大值127,於是它開始從最小值開始,搜尋一個合適的位置。同樣的道理,將129賦值給ch,ch的值會變成-127。
還有一個原理就是有符號和無符號資料的區別。我們知道,char也分為signed和unsigned兩種,前者是預設值,而後者的表示範圍是0~255。不管有無符號,這個區間的大小都是256,這也在情理之中,畢竟1個位元組由8個位組成,每個位可以取0或1,那麼一共就能表示2^8種不同的情況,2^8就是256。 同時,根據上面的理論,我們可以得出,將255賦值給ch,結果是-1。我們可以分別求出255和-1的補碼,它們都是11111111。當然,這不是什麼巧合,這是有科學道理的。255是unsigned char的最大值,它也是signed char能表示的負數中的最大值。當一個char是unsigned型別的時候,它的第一位自然不會被認為是符號位,所以11111111能表示255,而當這個char是signed型別時,第一位被解析成符號位,結果就是-1了。c.對繞回和同餘的解釋
-336的無符號整數是65200呢?書上說是2的補碼(書中描述):數字0到32767代表它們本身,而數字32768到65535則代表負數,65535代表-1,65534代表-2,依次類推,因此-336由65536-336,也即65200來表示;
d.同餘
很多人並不理解補碼。補碼就是同餘啊。1000000是正128你知道吧,正負128模256是同餘的。加減乘可以直接算也是同餘的定理決定的,而不是湊出來的巧合,哪可能湊出這種東西?
8位只能表示256個數,0到255,但我還想表示一些負數怎麼辦呢?就用與該負數同餘的正數來表示唄。-1=255,-2=254,等等。
建議脫離算數的思維方式,這其實就是一個環。模任何一個正整數(如256),可以把所有整數分類,比如模256可分256類,0 256 -256...是一類(餘0類),1 257 -255...是一類(餘1類),等等,這256類可看作環的元素,你看-128和128是同一個類裡的(餘128類),用一個代表另一個罷了。補碼和普通的unsigned integers都是在每類中選一個數,unsigned integers選0到255,補碼錶示的有符號整數選-128到127,都是一個數恰好對應一個類。
當你明白這一切後,補碼就是順理成章的事。
e.8位有符號數的列表 記憶體中8位二進位制10000000表示 -128-1<--->11111111 -2<--->11111110 -126<--->10000010 -127<--->10000001 -128<--->10000000
127<--->01111111 126<--->01111110 125<--->01111101 002<--->00000010 001<--->00000001 000<--->00000000