在計算機中,原碼、反碼、補碼 是用於表示有符號整數的三種編碼方式,主要用於解決二進制數的 正負表示 和 加減運算 問題。它們的核心區別在於 符號位的處理 和 負數的表示方法。
原碼(Sign-Magnitude)
定義
- 最高位(最左邊的一位)表示符號:
0表示正數(如+5)1表示負數(如-5)
- 其餘位表示數值的絕對值。
示例(8位二進制)
| 十進制 | 原碼錶示(8位) |
|---|---|
| +5 | 0000 0101 |
| -5 | 1000 0101 |
特點
✅ 直觀:和人類書寫習慣一致(正負號+數值)。
❌ 問題:
+0和-0不唯一:+0=0000 0000-0=1000 0000(計算機無法區分)
- 加減運算複雜:
- 需要額外判斷符號位,硬件實現麻煩。
反碼(Ones' Complement)
定義
- 正數:和原碼相同。
- 負數:在原碼基礎上,符號位不變,數值位取反(
0→1,1→0)。
示例(8位二進制)
| 十進制 | 反碼錶示(8位) |
|---|---|
| +5 | 0000 0101 |
| -5 | 1111 1010 |
| 十進制運算 | 反碼計算 | 反碼計算結果(十進制) |
|---|---|---|
| 1 +(-1)= 0 | [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 | -0 |
| 1 +(-2)= -1 | [0000 0001]反 + [1111 1101]反 = [1111 1110]反 = [1000 0001]原 | -1 |
| -1 +(2)= 1 | [1111 1110]反 + [0000 0010]反 = [0000 0000]反(溢出) = [0000 0000]原 | 0(溢出歸0) |
從上表可以看出,如果用反碼直接進行計算,雖然有所改善,但仍有問題,所以計算機中的運算也不能直接用反碼。
特點
仍然存在 +0 和 -0 問題
+0=0000 0000-0=1111 1111(仍然無意義)
運算仍需調整:
- 加減法後可能需要 “循環進位”(如
1 + (-1)=0000 0001+1111 1110=1111 1111(-0),需要額外加1修正)。
補碼(Two's Complement)⭐(現代計算機標準)
定義
- 正數:和原碼相同。
- 負數:在反碼基礎上 +1(即
原碼取反 + 1)。
示例(8位二進制)
| 十進制 | 補碼錶示(8位) |
|---|---|
| +5 | 0000 0101 |
| -5 | 1111 1011 |
計算 -5 的補碼
+5原碼 =0000 0101- 取反 =
1111 1010(反碼) - +1 =
1111 1011(補碼)
舉個例子,如果是8位的二進制數:
[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]補
[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]補
[-2] = [1000 0010]原 = [1111 1101]反 = [1111 1110]補
| 十進制運算 | 補碼計算 | 補碼計算結果(十進制) |
|---|---|---|
| 1 +(-1)= 0 | [0000 0001]補 + [1111 1111]補 = [0000 0000]補 = [0000 0000]原 | 0(溢出位捨棄) |
| 1 +(-2)= -1 | [0000 0001]補 + [1111 1110]補 = [1111 1111]補 = [1111 1110]反 = [1000 0001]原 | -1 |
| -1 +(2)= 1 | [1111 1111]補 + [0000 0010]補 = [0000 0001]補 = [0000 0001]原 | 1(溢出位捨棄) |
從上表可以看出,如果使用補碼進行計算,就可以正常的進行加法算術運算了。
特點
✅ 解決所有問題:
-
+0和-0統一:+0=0000 0000-0:原碼1000 0000→ 反碼1111 1111→ 補碼0000 0000(和+0相同)。
-
加減法直接運算:
5 + (-3)=0000 0101+1111 1101=0000 0010(2,正確)。
-
表示範圍更大:
- 8位補碼範圍:
-128(1000 0000)~+127(0111 1111),比原碼/反碼多一個數(-128)。
- 8位補碼範圍:
那麼至此,總結兩個非常重要的結論:
- 正數的原碼反碼補碼是一致的,負數的反碼是原碼除符號位取反,補碼是反碼+1。
- 計算機中有符號整數的存儲方式都是以補碼的形式存儲的,運算也是以補碼的形式計算的。
三種編碼對比(8位二進制)
| 十進制 | 原碼 | 反碼 | 補碼 |
|---|---|---|---|
| +5 | 0000 0101 |
0000 0101 |
0000 0101 |
| -5 | 1000 0101 |
1111 1010 |
1111 1011 |
| +0 | 0000 0000 |
0000 0000 |
0000 0000 |
| -0 | 1000 0000 |
1111 1111 |
0000 0000 |
| -128 | 無法表示 | 無法表示 | 1000 0000 |
為什麼計算機使用補碼
- 統一
+0和-0,避免歧義。- 加減法可以直接運算,無需額外判斷符號。
- 硬件實現簡單,CPU 只需加法器,無需額外電路。
- 表示範圍更大(如 8 位補碼可表示
-128~127,而原碼/反碼只能-127~127)。
常見問題
補碼 1000 0000 代表多少
- 在 8 位補碼中,
1000 0000表示-128(沒有對應的原碼/反碼)。
補碼的運算溢出怎麼辦
- 例如
127 + 1=0111 1111+0000 0001=1000 0000(-128,溢出)。 - CPU 會設置 溢出標誌位(OF),由程序員處理。
總結
| 編碼 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 原碼 | 直觀 | ±0 問題,運算複雜 |
早期計算機(已淘汰) |
| 反碼 | 改進負數表示 | ±0 仍存在,運算需調整 |
過渡方案(基本不用) |
| 補碼 | 無 ±0 問題,運算簡單 |
負數計算稍複雜 | 現代計算機標準 |
補碼是計算機存儲和處理有符號整數的 最優方案,理解它對於學習 計算機組成原理、編程(如整數溢出)、逆向工程 都至關重要!