# 概念
**原码**:符号位+真值,符号位0代表正,1代表负。
**反码**:正数的反码是其本身,负数的反码是符号位以外的各位取反。
**补码**:正数的补码是其本身,负数的补码是反码加1(符号位也参与运算,这个不用太在意,因为只有求负零的补码才会影响到符号位,而正零和负零是一样的)
# 取反相当于什么?
我们知道,在计算机中无论加减都是按照其补码相加的和求结果,因为2-1相当于2+(-1),那么为什么用补码就能实现呢?原理是什么?
先弄清取反相当于什么运算。例子:1010取反是0101,101110取反是010001。
我的理解方法有两种,第一种:对一个数取反就相当于用“全1”减这个数,“全1”就是各个位都是1。例子:1010取反是0101,1111-1010=0101。
第二种:可以按十进制来理解,因为还没搞懂LaTeX怎么使用,就先手写表示吧。

两种方法从数值上来看都是:当前位数能表示的最大值减去当前数。
# 原理
**一句话简单理解就是:用0\~10表示-5\~5**
实际在二进制中,如4位二进制,就是用0\~15表示-7\~7,其中0\~7还是表示0\~7,8\~15表示-7\~-1
原码运算3-5=-2,补码中实际是3+10=13,补码13换算成原码就是-2
可能还是没讲清楚。。。。表达能力不好
# 相关问题
在知乎上看到一个问题:
C语言十进制转八进制负数转法出现问题?
```c
#include <stdio.h>
void main()
{
int a=-7;
printf("a1=%o,a2=%5o\n",a,a);
}
```
运行结果是```37777777771```
这里的关键点是```%o```表示的是打印无符号八进制数,即```unsigned int```。
但```37777777771```是怎么算出来的,我们分析一下计算机内部的实际数据。
int用4字节保存,即32位,第一位是符号位。
```-7```在内存中的保存形式(补码):
原码:```1000 0000 0000 0000 0000 0000 0000 0111```
反码:```1111 1111 1111 1111 1111 1111 1111 1000```
补码:```1111 1111 1111 1111 1111 1111 1111 1001```
如果把这个补码当作```unsigned int```来输出(原反补码都一样)
```(0)11 111 111 111 111 111 111 111 111 111 001``` 最前面补一个零方便计算
上面这个数按八进制换算成十进制就是```37777777771```
《编译原理》复习笔记——原码、反码、补码