Altifigence Academy

8 / 37 · 概念

二補數、符號擴展與溢位

透過公式與反例,區分位元序列的 signed 解讀與加法溢位條件。

最高有效位元的權重改變了

NN 位元二補數二補數以固定寬度的位元序列表示帶符號整數。n 位元範圍為 −2^(n−1) 至 2^(n−1)−1。整數解讀如下。

s=−bN−12N−1+∑i=0N−2bi2is=-b_{N-1}2^{N-1}+\sum_{i=0}^{N-2}b_i2^i
−2N−1≤s≤2N−1−1-2^{N-1}\le s\le 2^{N-1}-1

4 位元 1010 以 unsigned無符號(unsigned)將位元序列解讀為非負整數。n 位元範圍為 0 至 2^n−1;相同位元序列的帶符號解讀可能得到不同數值。 詳細內容 解讀為 10,以 signed 解讀為 −6;不是把符號位元拿掉,再將其餘部分當成絕對值。固定寬度下,−x-x 可由位元反相反相是將 0 變為 1、1 變為 0 的 NOT 運算。公式上方的橫線表示對線下的整個運算式套用 NOT。 詳細內容再加 1 得到,但最小值 −8 對應的正數 +8 不在同樣的 4 位元 signed 範圍內。

擴展必須保留數值

unsigned 擴展在前方補 0,signed 擴展則補原本的符號位元。1010 變成 00001010 是 +10,變成 11111010 才是 −6。即使擴展相同位元,解讀方式不同,所需電路也不同。

SystemVerilog
logic signed [3:0] a, b;
logic signed [4:0] exact;
logic [3:0] result;
logic overflow;
assign exact = {a[3], a} + {b[3], b};
assign result = exact[3:0];
assign overflow = (a[3] == b[3]) && (result[3] != a[3]);

本例是兩個運算元、無 carry 輸入的 signed 加法。將 5 位元總和保留在 exact,再檢查縮窄結果的符號是否正確。

起始值設為 11111010。請確認 unsigned 250 與 signed −6 是同一位元序列;改變 b7 時,兩種解讀的數值會往不同方向變化。

相同 8 位元的符號解讀方式

11111010 → unsigned 250 · signed -6 · hex 0xFA

Carry 與 signed overflow 不同

V=aN−1⊕bN−1‾ (sN−1⊕aN−1)V=\overline{a_{N-1}\oplus b_{N-1}}\,(s_{N-1}\oplus a_{N-1})

相同符號的數相加,結果卻變號,就是 overflow。4 位元的 7+37+3 存成 1010,看起來是 −6;−8+(−1)-8+(-1) 存成 0111,看起來是 +7。兩個異號數相加不會發生這種超出範圍。

混合 signed 與 unsigned 的 RTL 運算式容易使比較、擴展規則混淆。請明確指定兩運算元的寬度與符號性,並將最小值、−1、0、最大值納入邊界測試。

自己試試看

求 4 位元 signed 的 −3+(−4)-3+(-4) 與 5+55+5 所儲存的位元序列及 overflow,並說明 −8-8 取負的結果。

查看解說

−7-7 為 1001,沒有 overflow。10 超出範圍,存成 1010(−6),因此發生 overflow。−8 反相加 1 後仍留下 1000,因為同寬度無法表示 +8,不能將其當成正確的絕對值計算。

此選擇適用於本瀏覽器,隨時可從頁尾變更。