資料表示法與數字系統

二補數(two's complement)

二補數是幾乎每一台現代電腦儲存有號整數的方式,值得理解它為何如此徹底勝出。聰明的點子是讓最高位元帶有負的權重。在一個 n 位元的數裡,最高位元不再值 +2^(n-1),而是值負 2^(n-1),其餘所有位元保留正常的正位值。所以在 8 位元裡,最高位元值 -128,其餘值 +64、+32、…、+1。負數就只是最高有效位元被設為 1 的數。

也有一個取負的快速食譜:翻轉每個位元,然後加一。取 8 位元的 +5,0000 0101;翻轉得到 1111 1010;加一得到 1111 1011,就是 -5。用位值驗證:-128 + 64 + 32 + 16 + 8 + 2 + 1 = -5。兩個致勝優勢由這個設計自然落下。第一,剛好只有一個零:0000 0000,沒有獨立的負零,因為把零翻轉再加一會俐落地繞回零。第二,也是讓硬體設計者歡呼的原因,加法與減法用的是和無號數完全相同的二進位加法器——要算 a 減 b,你只要把 a 加上 b 的二補數負值,所以一個加法器電路同時服務有號與無號,毫無特殊的符號處理邏輯。

代價是範圍不對稱。一個 n 位元二補數從負 2^(n-1) 到 2^(n-1) 減 1——8 位元就是 -128 到 +127。負值比正值多一個,因為那唯一的零坐在正的一側。這造成一道真實的硬邊:最負的數沒有正的對應,所以在 8 位元裡對 -128 取負會溢位、又回到 -128。知道這點是真正的工程而非冷知識——那少掉的一個正值造成過實際的 bug,例如對最負整數取絕對值。

在 8 位元二補數裡算 7 減 3:-3 是 1111 1101(把 0000 0011 翻轉成 1111 1100、再加一)。於是 0000 0111 + 1111 1101 = 0000 0100,也就是 4(從左端掉出的進位直接丟棄)。一個加法器就完成了減法。

把減法當成加上一個取負的運算元——同一個加法器服務有號與無號。

範圍是歪的:n 位元涵蓋負 2^(n-1) 到 2^(n-1) 減 1,所以最負的值沒有正的雙胞胎。對它取負會溢位回到自身——這是取絕對值時真實的 bug 來源。

又稱
twos complement2's complement補數表示法