補碼是為了解決計算機的減法問題,計算的本質是取模。
計算機只有加法運算器,沒有減法,所以引入符號位,例1001表示-1;
注:從硬體的角度上看,只有正數加負數才算減法。
正數與正數相加,負數與負數相加,其實都可以通過加法器直接相加。
2.引入符號位後會出現問題(因為要用負數表示減法,所以這裡符號位也有參與運算)
例:0001+1010=1011 即:1+(-2)=(-3)有問題
1001+1010=10011(溢位)=0011 即:(-1)+(-2)=3有問題
結果:因為符號位的關係,正數相加沒問題,但正負數相加和負數相加有問題,
3.為解決第2步的問題,引入反碼,
注:正數的反碼還是原碼,負數的反碼為除符號位外,按位取反。
之後重新計算:
0001(1的反碼)+1101(-2的反碼)=1110(-1的反碼) 即:1+(-2)=(-1)沒問題
0010(2的反碼)+1110(-1的反碼)=10000(溢位)=0000(0的反碼) 即:2+(-1)=0有問題
1110(-1的反碼)+1101(-2的反碼)=11011(溢位)=1011(-4的反碼) 即:(-1)+(-2)=(-4)有問題
結果:正數相加沒問題,但正負數相加和負數相加還是有問題,
仔細觀察,發現沒溢位時是對的,溢位時結果就少了1;
這樣來看的話,反碼已經基本解決了減法的問題,但這樣還是不行。
4.為了解決第3步的問題,引入了補碼:
注:正數的補碼還是原碼,負數的補碼為反碼+1。
之後重新計算:
0001(1的補碼)+1110(-2的補碼)=1111(-1的補碼) 即:1+(-2)=(-1)沒問題
0010(2的補碼)+1111(-1的補碼)=10001(溢位)=0001(1的補碼) 即:2+(-1)=1沒問題
1111(-1的補碼)+1110(-2的補碼)=11101(溢位)=1101(-3的補碼) 即:(-1)+(-2)=(-3)沒問題
問題完美解決(感覺本質上就是為了不用到減法而使用補碼)
補碼的思想:
大部分的說法:
正數的補碼等於他的原碼
負數的補碼等於反碼+1。
另外一種說法:
負數的補碼等於他的原碼自低位向高位,尾數的第乙個『1』及其右邊的『0』保持不變,左邊的各位按位取反,符號位不變。
其實這兩種只是補碼的演算法而已。
補碼的實質就取模。
比如,現在是10點,如果把指標指向8點呢,答案是-2或者+10,
這裡為什麼10-2=10+10=8(點)呢
是因為(10-2)%12=(10+10)%12=8
當10+10>12時,相當於%12;10>=0,所以10的補碼為10(其實正數非要計算補碼也行,反正10 mod 12=10,只是沒必要);-2<0,-2的補碼為(-2+12)%12=10
再例如:四位二進位制數中,四位二進位制數只能表示0000~1111
-1000(-8)
編碼就是x mod 16
意思就是:非要用加法表示減法的話,可以讓數溢位,即模16
當x>0時,x mod 16 =x,即正數的補碼為正數,
當x<0時,x+16 mod 16的值就是補碼,效果就是取反加一
x=1,補碼:x mod 16 =1=0001
x=-1,補碼:x+16 mod 16=15=1111
x=-5,補碼:x+16 mod 16 = 11=1011
x=-8,補碼:x+16 mod 16=8=1000
2-1=2+(-1)=2+(-1+16)%16=2+15=17=10001(溢位)=0001=1,
相當於一天有16個小時(由二進位制的位數來決定),此時為2點,要把指標移動到1點,則可以退後一點,即-1,也可以往前推動15點(15相當於-2的補碼,計算是(-1+16)%16),此時會等於17點,指標多轉了一圈(相當於溢位),然後減16就等於1點了(因為位數的限制,所以任何數都要%16),因為指標只能向前不能向後(相當於計算機只有加法沒有減法,這是個巧合,強行解釋一下(*^_^*)),所以只能+15不能-1。這裡也不是很嚴謹,因為不好解釋1-2=(-1)。
再比如x= -5,說明指標要退5點,但因為只能前進,一天有16小時,所以需要前進11小時:(-5+16)%16=11。
從數學角度來證明:
1. 為什麼補碼等於反碼+1
假設有4位,以-5為例:
-5的補碼為:(-5+16)%16=16-5=10000-101=(1111+1)-101=(1111-101)+1=1011
其中1111-101相當於求-5的補碼(符號位一定為1,所以符號位不變),最後再+1。
2. 負數的補碼的補碼為什麼等於本身:
證明1:
還是假設有4位,設負數的數值位為x,
則x的補碼為:(-x+16)%16
x的補碼的數值位為(-x+16)%16-8;
x的補碼的補碼的數值位為(-((-x+16)%16-8)+16)%16-8
通過計算可得x=(-((-x+16)%16-8)+16)%16-8,即補碼的補碼的數值位保持不變;
證明2:
取-0=100000000……,記住10*,其中0*表示有0到無窮個0,1*表示有0到無窮個1,
在數值位上隨機取幾個1(假設為3個吧),則負數可表示為:10*10*10*10*,
原碼:10*10*10*10*,
反碼:11*01*01*01*,
補碼:11*01*01*10*,
補碼的反碼:10*10*10*01*,
補碼的補碼:10*10*10*10*,
從這邊就可以看出,前面三個部分補碼的情況和反碼是一樣的,最後一部分的變化為:10*(原碼)→01*(反碼)→10*(補碼)→01*(補碼的反碼)→10*(補碼的補碼)=10*(原碼)
3. 為什麼負數的反碼運算溢位時會少1:
略(以後有空再證明吧,似乎蠻難的但也不重要,就當作溢位的1應該進製到末位吧)
原碼 反碼 補碼分析
反碼 正數 反碼和原碼相同 負數 最高位為符號位為1,其餘位原碼取反 補碼 正數 原碼 反碼和補碼相同 負數 最高位符號位為1,其餘位為原碼取反,在對整個書加1 計算機中原碼用於表示有符號的正數和無符號整數 ex int x 1 在記憶體中十六進製制的表示方式為 0000 00001 0000 00...
原碼 反碼和補碼
數值有正負之分 計算機就用乙個數的最高位存放符號 0為正 1為負 這就是機器數的原碼了 假設機器能處理的位數為 8.即字長為 1byte,原碼能表示數值的範圍為 127 0 0 127 共256個.有了數值的表示方法就可以對數進行算術運算 但是很快就發現用帶符號位的原碼進行乘除運算時結果正確 而在加...
原碼 反碼 和 補碼。
這裡只講下自己對反碼的理解。大家都知道使用反碼表示負數有兩個優點,1.可以使得減法可以和加法一樣。2.符號位也參與了運算。那這是為什麼呢?下面可以進行一些簡單的數學推導 根據反碼定義,對於負數,反碼是除符號為以外取反 1。例如,4 變換步驟如下。a 4 0 000 0100 b 取反 0 111 1...