補碼(Two's complement),是有符号數的一種二進制表示方式。
我們用 B2Tw 來表示一個補碼。其中 w 代表二進制數的位長,B2T 的含義其實是 “二進制轉補碼”。
計算補碼實際表示的數,我們需要将每一位上的值和對應權重相乘然後進行相加。每一位(索引記為 i,從 0 開始,從右往左遞增)的權重為 2i,但最高位的權重比較特殊,需要取負數,為 -2w-1。
補碼的數學公式對向量 x = [x^(w-1), x^(w-2), ... , x^0],有:
下面舉幾個簡單的例子:
補碼其實就是将最高位後面的位當成是一個無符号二進制數,将其轉為十進制。然後如果最高位是 1,就再減去 2^(w-1),得到一個負數;
如果最高位是 0,不用處理,最後得到一個非負數。補碼這種表示方式使用了 減去偏移值(2^(w-1)) 的方式,解決了原碼和反碼表示的 0 有兩種表示方式的弊端,成為現在機器有符号數的标準意義上的存儲方式。
補碼表示的最大值和最小值對于一個位長為 w 的補碼表示,最大值 TMaxw 為 2^(w-1) - 1,此時最高位為 0,其餘位都是 1。最小值 TMinw 為 -2^(w-1),此時最高位為 1,其餘位都是 0。
如對于 4 位的補碼,最大值 TMax4 = B2T4([0111]),對應的值為 2^3 - 1 = 7,最小值為 B2T4([1000]),對應的值為 -2^3 = -8。
補碼(Two's complement)命名的由來補碼的英文 Two's complement,原意是 “2的補數”。
這個命名雖然沒有描述補碼的定義,但它描述了補碼的一個特性:一個補碼可以通過被 2w 減去,得到它的相反數,即 -x = 2w - x。
如對于字長為 4 的補碼表示 0001(十進制為 1),它的相反數為 10000(即 24) - 0001 = 1111(十進制為 -1)。
我們在學習原碼、反碼、補碼,查閱相關文章時,總是可以看到類似下面的這句話。
正數和0的補碼就是該數字本身,負數的補碼則是将其對應正數按位取反再加 1。
後半句話難以理解,因為這是我前文提到的特性的一種變體。下面我們來分析這個變體是如何推導出來的。
根據補碼特性,字長為 w 的補碼和補碼的相反數相加,得到的是 2^w,如 0001 1111 = 10000(即 24)。
補碼和補碼按位取反的數相加得到的是 2^w-1,如 0001 1110 = 1111(即 10000 - 1)。
用後一個等式減去前者,我們就得到了:
1111(負數的補碼) = 1110(正數按位取反) 1
于是我們有了 “負數的補碼則是将其對應正數按位取反再加 1” 這個結論。
請務必不要通過這句話來理解補碼,它不直觀,不是定義,隻是一個特性。
而是應該直擊本質:除最高位的其他位對應的數,根據最高位的值決定是否減去偏移值(2^w,w 為位長)得到的值就是補碼。
原碼與反碼既然講了補碼,那不妨再簡單講講和補碼密切相關的原碼和反碼。原碼和反碼和補碼一樣,都是有符号數的表示方式。
原碼(Sign Magnitude),由最高位的符号位(Sign)和其餘位表示的大小(Magnitude)組成。
原碼與我們日常使用的有符号數相似,最高位表示符号(0為正,1為負),剩下的位則是數字的絕對值大小。原碼的計算公式為:
反碼(Ones' Complement),和補碼的計算方式非常相似,隻是這個偏移值是 2^(w-1)-1,而不是 2^(w-1)。
正數的反碼等于其原碼,而負數的反碼則可以通過保留其符号位,将原碼的數值位取反得到。
反碼公式為:
反碼(Ones' Complement),根據英文原意,應該叫做 1們的補。“1們” 表示是多個 1,對于一個 w 位的反碼來說,其實就是 2^(w-1)-1(全為 1 的 w 位的二進制數)。
同樣,類似補碼,反碼具有特性:一個補碼可以通過被 2^w-1 減去,得到它的相反數,即 -x = 2^w-1 - x。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!