計算機采用二進制計數,有符號整數的表示、存儲和計算就是一個要解決的問題;
在這個問題上,計算機設計者選擇了補碼表示法。
在這之前,先看下另一種表示方法,符號及值表示法。
一個 n 位字可以表示從 0 ~ 2n-1 共 2n 個可能的值,如表 無符號數;表示負數的一種方法是用它的最高位表示符號,通常符號位為 0 表示正數,符號位為 1 表示負數;
有符號數的值可被表示為 (-1)s×M,這里 s 為數的符號位的值,M 為其數值部分;則其表示范圍為 -(2n-1-1) ~ +(2n-1-1),一個8位有符號數可以表示為 -127 ~ +127,如表 原碼
但有個問題, 0000 0000 = +0、1000 0000 = -0,且算術運算中需要使用減法器;因此計算機設計者選擇了只需要加法器就可以進行包含負數的運算,且能解決+0、-0問題的補碼表示系統。
補碼表示法,涉及到補數和模的概念;
舉例,8位字長,10 - 2 = 10 + (-2) = (10 + (256-2)) mod 256 = (10 + 254) mod 256 ;所以 -2 和 +254 效果是一樣的,那么 -2 就可以用 1111 1110 來存儲,用加法器算術運算。
這里猜測下為什么是 -128。256個數,正負各半,我們知道 0 既不是正數又不是負數,那么還剩 2 個數要怎么安排? 0000 0000、1000 0000;沒說的,0000 0000 肯定表示 0
現在數的表示范圍已經達到了 -127 ~ +127,1000 0000 最高位是1, 划分到負數合理,故只能是 -128;其實對模=256來說,-128 運算等價於 +128。
取反+1
例如, -N 要存放到計算機,負數先進行求補運算,28 - N = 1 0000 00002 - N = 1 0000 00002 - 1 - N + 1 = 1111 11112 - N + 1
1111 11112 - N 很容易計算,非常簡單,計算機易實現,這也是補碼的魅力;
另外對一個原碼 2 次 取反+1,仍是本身;
例如,存 a = -126 時,求補存放,然后進行算術運算,當 printf %d 的 時候,先進行一次取反+1就好。