首先,看這篇文章之前,你需要的是不必糾結,比如:為什么正數的原碼反碼補碼就一樣呢,負數的原碼反碼補碼就各不相同呢?
看這篇文章之前你只需要記住,這是人為規定的。你可能會想,為什么要這樣人為規定呢,我現在只能告訴你,這樣規定有利於計算機底層對數字進行操作,
也就是說,這種規定對計算機的底層硬件要求簡化了,技術實現起來更簡單。
我們日常用的數字是給我們人類用的,所以叫真值。而機器(計算機)理解的數字通常是二進制所組成的數字,所以稱為機器數。
二進制在內存中以補碼形式在其中存儲,計算機計算數字是通過補碼的形式進行計算的,也就是說不管正數,還是負數在計算機里面,都要用補碼來表示。
在原碼,反碼,補碼中,最高位來表示正負,用0表是正,1表示負;
如十進制的10表示為:+1010--->原碼:0 1010;-1010--->原碼: 1 1010;
筆記一:原碼,反碼,補碼
*規則:
正數中:原碼=反碼=補碼;例子拿上面的:+1010---> 0 1010;
+1010--->原碼: 0 1010;(最高位0表示正號)
+1010--->反碼: 0 1010;
+1010--->補碼: 0 1010;
+1010--->移碼: 1 1010(補碼符號位取反)
負數中的規則如下:例子拿上面的:-1010---> 1 1010;
-1010--->原碼: 1 1010;(最高位1表示負號)
-1010--->反碼: 1 0101;(符號位不變,數值位:0變1,1變0)
-1010--->補碼: 1 0110;(符號位不變,數值位:0變1,1變0。最后得出來的數字再加1。簡單點總結為:“反碼加1”)
-1010--->移碼: 0 0110(補碼符號位取反)
最后注釋:移碼:無論正負數,都是補碼的符號位取反。
還有這里解釋一下,為什么計算機實際計算數字是用補碼進行運算的,如果你看了我上面的例子的話,應該清楚了,不管是正數,還是負數,在計算機中,補碼最高位都是1,
意思就是說,補碼的作用,把正數規定還是正數,而負數還是負數,但是正負數進行運算的時候轉變為加法形式,例如:3-5變成3+(-5).這樣子,計算機底層很容易實現加法運算。
這樣子我們設計程序的時候,實際在設計加法運算。
推薦你看一下這篇文章:https://www.jianshu.com/p/2f9630dd2016,因為如果負數不采用補碼進行運算,那么其實會發生溢出的。
再講深一點的話:
關於補碼,我們做進一步解釋:
(1)化減為加:
由於計算中的CPU只有加法器,沒有減法器,采用補碼可以化減數運算為加數,例如原來的:1-1=0,化為計算機可處理的1+(-1)=0
(2)10000000與00000000都是零嗎?——關於-128的由來
補碼還解決了原碼中存在兩個0 的問題(即+0 和 -0),以8進制為例,java中byte的取值范圍應該是-127~ -0和+0~ 127 即存在-0和+0 ,
但是在兩個0轉換為補碼后,分別為10000000和00000000,00000000它還是0,但是我們人為地規定10000000表示-128,這就是上面取值范圍中-128的由來。
這里再強調一下,10000000和00000000都是補碼,而不是原碼。
如果你還想了解為什么需要反碼,補碼,可以看看另外一篇文章:https://www.cnblogs.com/hmy-666/p/12551063.html
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
筆記二:取反。
注意:取反運算不等同於求反碼!
*“~”這個小波浪號叫取反(下面例子都是10進制化2進制取反)。~10=-11,~(-10)=9。
規則:對一個數進行取反運算時,先對這個數按位取反得出值X1,再對X1求補碼,即得出結果。
例子:對57進行取反。
其57按位取反后二進制表示為(表示一個字節 8bit) 1100 0110
1100 0110 (最前面的第一位表示符位 )
1表示次數為負數
1100 0110 可表示為 -(2^6+2^2+2^1) = -70;
不管正數,還是負數在計算機里面,都要用補碼來表示
即補碼=符號位以后的按位取反后加1
反之減1
所以 -70 = 1100 0110 符號位以后按位取反后再加一為 1011 1010 = -58
即~57 = -58;
負數反之即可。
其實簡單點,這個符號的運算法則是:如果一個數取反,那么值等於這個數的相反數再減去1。總結:~X=(-X-1)。
------------------------------------------------------------------------------------------------------------------------------------------------------
注:八位二進制擴展到十六位二進制
負數擴展,擴展的高位不斷補1
-13
8位原碼:1000 1101
8位補碼:1111 0011
16位補碼:1111 1111 1111 0011 根據負數轉換規則由16位補碼可以推出16位原碼:1000 0000 0000 1101
根據前面的知識,由於-13的最高位為1,所以直接在最高位前面添加8個1即可變為16位補碼,即1111 1111 1111 0011(與前面由原碼求補碼的結果一致)。
正數擴展,擴展的高位不斷補0
13
8位原碼:0000 1101
8位補碼:0000 1101
16位補碼:0000 0000 0000 1101 根據正數轉換規則由16位補碼可以推出16位原碼:0000 0000 0000 1101
根據前面的知識,由於13的最高位為0,所以直接在最高位前面添加8個0即可變為16位補碼,即0000 0000 0000 1101(與前面由原碼求補碼的結果一致)。
注:除了1000 0000人為規定為-128外,其它都是根據規則轉換為原碼輸出的形式