# 原码、反码、补码原码、反码、补码
<!--more-->


# 原码、反码、补码

封面： https://www.mylittlewallpaper.com/c/vocaloid/download/5381c1271f52d0.23342334

计算机使用二进制表示数值，但是二进制没有正反，那么如何使用二进制表示正反呢？

原码、反码、补码就是解决这个问题的：

- **原码**（Sign-Magnitude）
- **反码**（Ones' Complement）
- **补码**（Two's Complement）← **现代计算机标准**

## 原码（Sign-Magnitude）

### 表示方法：

- 最高位表示符号：0为正，1为负
- 其余位表示数值的绝对值

**负数表示也就是：取出最左边的位（最高位）表示正反**

### 示例（4位）：

```text
+5：0101
-5：1101

```

### 问题：

- 有+0和-0两种零：`0000`和`1000`
- 加减法电路复杂

## 反码（Ones' Complement）

### 表示方法：

- **正数**：与原码相同
- **负数**：将对应正数的**所有位取反**（0变1，1变0）

**负数表示也就是：符号位不变，其余取反**

### 计算规则：

```TEXT
负数 = 按位取反(对应正数)

```

### 示例（4位）：

```text
+5：0101
-5：1010  （将0101的每一位取反）

```

### 验证：5 + (-5) = 0

```text
  0101 (+5)
+ 1010 (-5)
-----------
  1111  （这是-0的反码表示）
  
```

### 特点：

- 仍然有+0（0000）和-0（1111）的问题
- 加减法比原码简单，但仍有循环进位问题

## 补码（Two's Complement）← **现代标准**

### 表示方法：

- **正数**：与原码相同
- **负数**：将对应正数的**所有位取反后加1**

**负数表示也就是反码+1**

### 计算规则：

```text
负数 = 按位取反(对应正数) + 1

```

### 示例（4位）：

```text
+5：0101
-5：1011  （将0101取反得1010，再加1得1011）

```

### 验证：5 + (-5) = 0

```text
  0101 (+5)    正数不需要改变
+ 1011 (-5)    负数使用补码
-----------
 10000  （4位系统中，最高位进位，被丢弃，只留4位）
  0000  = 0 ✓

```

## 三种编码对比（4位系统）

|十进制|原码|反码|补码|
|---|---|---|---|
|+7|0111|0111|0111|
|+6|0110|0110|0110|
|+5|0101|0101|0101|
|+4|0100|0100|0100|
|+3|0011|0011|0011|
|+2|0010|0010|0010|
|+1|0001|0001|0001|
|+0|0000|0000|0000|
|-0|1000|1111|无|
|-1|1001|1110|1111|
|-2|1010|1101|1110|
|-3|1011|1100|1101|
|-4|1100|1011|1100|
|-5|1101|1010|1011|
|-6|1110|1001|1010|
|-7|1111|1000|1001|
|-8|无|无|1000|
## 总结

|特性|原码|反码|补码|
|---|---|---|---|
|零的表示|+0和-0|+0和-0|唯一0|
|加减法|复杂|较简单|统一简单|
|硬件需求|多|较少|最少|
|现代使用|基本不用|很少用|**标准**|


---
**补码是现代计算机表示有符号整数的标准**，它解决了零的歧义问题，成为了最终的计算机负数计算的**最终解决方案**。